Skip to content

Commit

Permalink
Merge f703384 into 2871ed3
Browse files Browse the repository at this point in the history
  • Loading branch information
codesankalp committed Jul 14, 2021
2 parents 2871ed3 + f703384 commit 58a6c7c
Show file tree
Hide file tree
Showing 76 changed files with 4,339 additions and 2,846 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ client/assets/*
!client/assets/eye-slash.svg
!client/assets/default/
!client/assets/fonts/
client/translations/
i18n/*
!i18n/*.po
server/config.json
compilation-stats.json

Expand Down
80 changes: 73 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ and `method` property.

Let us consider the following configuration for the header, footer and contact components:

```
```yaml
components:
header:
links:
Expand Down Expand Up @@ -353,12 +353,6 @@ login_form:
auto_switch_phone_input: false
type: "text"
pattern: null
pattern_description:
en: null
placeholder:
en: "username, email or mobile phone number"
label:
en: "username, email or mobile phone number"
```

#### Configuring Social Login
Expand Down Expand Up @@ -420,6 +414,78 @@ enable this feature, just create a new organization with the

`Are you using OpenWISP Subscriptions to provide paid subscriptions for WiFi plans or identity verification via credit/debit card?`

#### Translations

1. Translations are loaded at runtime from the JSON files that were compiled during the build process.
2. By default, the build process uses the `{language_code}.po` files to generate
the translations.
3. `{language_code}.custom.po` file can be used to override the `{language_code}.po`
file. The custom files need not to be duplicate of the default file i.e. translation
can be defined as the custom strings.
4. Translation can also be generated for single organisation if `{orgSlug}_{language_code}.custom.po` is present in `i18n` Directory.
5. Translation can be created by running the command:
`yarn create-translation {language_code} i18n/{file_name}.po`

Here `file_name` can be `{orgSlug}_{language_code}.custom.po`, `{language_code}.custom.po\` or
`{language_code}.po`.

6. Translations inside `i18n/` directory can be updated by using this command:
`yarn update-translation i18n/{file_name}.po client/`

This will update all the translations by replacing the placeholder defined in the `client/`.

7. If there is more than one language in `i18n/` directory then update the organization configuration file by adding the support for that language like this:

```yaml
languages:
- text: "english"
slug: "en"
- text: "Spanish"
slug: "es"
```

#### Customizing Translations

1. **Organization specific customization**:

- Create a translation file with name `{orgSlug}_{language_code}.custom.po` by running:
`yarn create-translation <language-code> i18n/{orgSlug}_{language_code}.custom.po`
- Now to override the translation placeholders (`msgid`) add the `msgstr` in the newly generated file for that specific `msgid`:

```
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals = 2; plural = (n != 1);\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "PHONENUMBER_LABEL"
msgstr "mobile phone number (verification needed)"
```

2. **Language specific customization**:

- Create a translation file with name `{language_code}.custom.po` by running:
`yarn create-translation <language-code> i18n/{language_code}.custom.po`
- Now to override the translation placeholders (`msgid`) add the `msgstr` in the newly generated file for that specific `msgid`:

```
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals = 2; plural = (n != 1);\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "FORGOT_PASSWORD"
msgstr "Forgot password? Reset password"
```

**Note**: Do not remove the content headers from the `.po` files as it is needed during the build process.

### License

See [LICENSE](https://github.com/openwisp/openwisp-wifi-login-pages/blob/master/LICENSE).
7 changes: 2 additions & 5 deletions client/actions/dispatchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
SET_USER_DATA,
SET_PAGE_TITLE,
} from "../constants/action-types";
import getText from "../utils/get-text";

export const authenticate = (dispatch) => {
return (status) => {
Expand All @@ -28,9 +27,7 @@ export const setTitleAction = (title) => {
};
};
export const setTitle = (dispatch) => {
return (component, language, orgName) => {
dispatch(
setTitleAction(`${getText(component.title, language)} - ${orgName}`),
);
return (componentTitle, orgName) => {
dispatch(setTitleAction(`${componentTitle} - ${orgName}`));
};
};
29 changes: 12 additions & 17 deletions client/components/404/404.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,36 @@ import "./index.css";
import PropTypes from "prop-types";
import React from "react";
import {Link} from "react-router-dom";

import getText from "../../utils/get-text";
import {t} from "ttag";

export default class DoesNotExist extends React.Component {
componentDidMount() {
const {orgName, setTitle, page, language} = this.props;
const {orgName, setTitle, page} = this.props;
if (page !== undefined || orgName !== undefined)
setTitle(page, language, orgName);
setTitle(t`404_PAGE_TITLE`, orgName);
}

render() {
const {orgSlug, language, page} = this.props;
const {orgSlug, page} = this.props;
return (
<div className="container content" id="not-foud-404">
<div className="inner">
<div className="main-column">
<div className="row owisp-404-row-1">
{page && page.heading ? getText(page.heading, language) : "Oops!"}
{page && page.heading ? t`404_HEADING` : "Oops!"}
</div>
<div className="row owisp-404-row-2">
{page && page.sub_heading
? getText(page.sub_heading, language)
: "404 Not Found"}
{page && page.sub_heading ? t`404_SUBHEADING` : "404 Not Found"}
</div>
<div className="row owisp-404-row-3">
{page && page.message
? getText(page.message, language)
? t`404_MESSAGE`
: "Sorry, an error has occurred, Requested page not found!"}
</div>
{page && page.homepage_link && (
<div className="row owisp-404-row-4">
<Link to={`/${orgSlug}`} className="link">
{getText(page.homepage_link.text, language)}
{t`HOME_PAGE_LINK_TEXT`}
</Link>
</div>
)}
Expand All @@ -48,13 +45,11 @@ export default class DoesNotExist extends React.Component {
}
DoesNotExist.propTypes = {
page: PropTypes.shape({
title: PropTypes.object,
heading: PropTypes.object,
sub_heading: PropTypes.object,
message: PropTypes.object,
homepage_link: PropTypes.object,
heading: PropTypes.bool,
sub_heading: PropTypes.bool,
message: PropTypes.bool,
homepage_link: PropTypes.bool,
}),
language: PropTypes.string,
orgSlug: PropTypes.string,
orgName: PropTypes.string,
setTitle: PropTypes.func,
Expand Down
23 changes: 17 additions & 6 deletions client/components/404/404.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import React from "react";
import ShallowRenderer from "react-test-renderer/shallow";
import {shallow} from "enzyme";
import getConfig from "../../utils/get-config";
import loadTranslation from "../../utils/load-translation";
import DoesNotExist from "./404";

jest.mock("../../utils/load-translation");

const defaultConfig = getConfig("default");
const createTestProps = (props) => {
return {
language: "en",
orgSlug: "default",
orgName: "default name",
page: defaultConfig.components["404_page"],
Expand All @@ -16,7 +18,20 @@ const createTestProps = (props) => {
};
};

describe("<DoesNotExist /> rendering with placeholder translation tags", () => {
const props = createTestProps();
it("should render translation placeholder correctly", () => {
const renderer = new ShallowRenderer();
const wrapper = renderer.render(<DoesNotExist {...props} />);
expect(wrapper).toMatchSnapshot();
});
});

describe("<DoesNotExist /> rendering", () => {
beforeEach(() => {
loadTranslation("en", "default");
});

it("should render correctly default 404 page without props", () => {
const renderer = new ShallowRenderer();
const component = renderer.render(<DoesNotExist />);
Expand All @@ -34,10 +49,6 @@ describe("<DoesNotExist /> rendering", () => {
const props = createTestProps();
const wrapper = shallow(<DoesNotExist {...props} />);
const setTitleMock = wrapper.instance().props.setTitle.mock;
expect(setTitleMock.calls.pop()).toEqual([
props.page,
props.language,
props.orgName,
]);
expect(setTitleMock.calls.pop()).toEqual(["404 Not found", props.orgName]);
});
});
41 changes: 41 additions & 0 deletions client/components/404/__snapshots__/404.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,44 @@ exports[`<DoesNotExist /> rendering should render correctly default 404 page wit
</div>
</div>
`;

exports[`<DoesNotExist /> rendering with placeholder translation tags should render translation placeholder correctly 1`] = `
<div
className="container content"
id="not-foud-404"
>
<div
className="inner"
>
<div
className="main-column"
>
<div
className="row owisp-404-row-1"
>
404_HEADING
</div>
<div
className="row owisp-404-row-2"
>
404_SUBHEADING
</div>
<div
className="row owisp-404-row-3"
>
404_MESSAGE
</div>
<div
className="row owisp-404-row-4"
>
<Link
className="link"
to="/default"
>
HOME_PAGE_LINK_TEXT
</Link>
</div>
</div>
</div>
</div>
`;
1 change: 0 additions & 1 deletion client/components/404/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Component from "./404";
const mapStateToProps = (state) => {
return {
page: state.organization.configuration.components["404_page"],
language: state.language,
orgSlug: state.organization.configuration.slug,
orgName: state.organization.configuration.name,
};
Expand Down
71 changes: 71 additions & 0 deletions client/components/contact-box/__snapshots__/contact.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,76 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Contact /> rendering with placeholder translation tags should render translation placeholder correctly 1`] = `
<div
className="side-column contact"
>
<div
className="inner"
>
<div
className="row"
>
<span
className="label"
>
EMAIL
:
</span>
<a
className="link"
href="mailto:support@openwisp.co"
>
support@openwisp.co
</a>
</div>
<div
className="row"
>
<span
className="label"
>
HELPDESK
:
</span>
<a
className="link"
href="tel:+789 948 564"
>
+789 948 564
</a>
</div>
<div
className="contact-links"
>
<a
className="link "
href="https://twitter.com/openwisp"
rel="noopener noreferrer"
target="_blank"
>
<img
alt="twitter"
className="contact-image "
src="/assets/default/twitter.svg"
/>
</a>
<a
className="link "
href="https://facebook.com/openwisp"
rel="noopener noreferrer"
target="_blank"
>
<img
alt="facebook"
className="contact-image "
src="/assets/default/facebook.svg"
/>
</a>
</div>
</div>
</div>
`;

exports[`<Status /> rendering should render correctly 1`] = `
<div
className="side-column contact"
Expand Down
Loading

0 comments on commit 58a6c7c

Please sign in to comment.