Skip to content

Commit

Permalink
Prepare for JS i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
jsmesami committed Mar 5, 2024
1 parent 8c52606 commit 402beb7
Show file tree
Hide file tree
Showing 19 changed files with 184 additions and 37 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ To run the tests, check your test coverage, and generate an HTML coverage report
pip install -r requirements/test.txt
npm run test

### Prepare locale messages

npm run msg:make # Collect strings for translation
npm run msg:compile # Compile translation catalogues

### Email Server

In development, it is often nice to be able to see emails that are being sent from your application.
Expand Down
3 changes: 2 additions & 1 deletion config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pathlib import Path

import environ
from django.utils.translation import gettext_noop

BASE_DIR = Path(__file__).resolve(strict=True).parent.parent.parent
# tumbs/
Expand All @@ -30,7 +31,7 @@
# https://docs.djangoproject.com/en/dev/ref/settings/#languages

LANGUAGES = [
("en", "English"),
("en", gettext_noop("English")),
("cs", "Čeština"),
]
# https://docs.djangoproject.com/en/dev/ref/settings/#site-id
Expand Down
3 changes: 3 additions & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.urls import include, path
from django.views import defaults as default_views
from django.views.generic import TemplateView
from django.views.i18n import JavaScriptCatalog, set_language
from ninja import NinjaAPI

api = NinjaAPI(version="1.0.0")
Expand All @@ -14,6 +15,8 @@
path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
# Django Admin, use {% url 'admin:index' %}
path(settings.ADMIN_URL, admin.site.urls),
path("jsi18n/cms/", JavaScriptCatalog.as_view(packages=["tumbs.websites"]), name="cms-i18n"),
path("set-lang/", set_language, name="set_language"),
# App stuff
path("accounts/", include("tumbs.accounts.urls", namespace="accounts")),
path("websites/", include("tumbs.websites.urls", namespace="websites")),
Expand Down
8 changes: 7 additions & 1 deletion locale/cs/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-01 22:27+0000\n"
"POT-Creation-Date: 2024-03-05 00:04+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand All @@ -19,6 +19,9 @@ msgstr ""
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n "
"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"

msgid "English"
msgstr "English"

msgid "Accounts"
msgstr ""

Expand Down Expand Up @@ -51,6 +54,9 @@ msgstr ""
msgid "My Site"
msgstr ""

msgid "Language"
msgstr ""

msgid "Customer"
msgstr ""

Expand Down
73 changes: 73 additions & 0 deletions locale/cs/LC_MESSAGES/djangojs.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-04 23:22+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n "
"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"

msgid "No site yet"
msgstr ""

msgid "My New Site"
msgstr ""

msgid "Homepage"
msgstr "Domů"

#, javascript-format
msgid "Could not create site: %s"
msgstr ""

msgid "Create Site"
msgstr ""

msgid "Available websites"
msgstr ""

#, javascript-format
msgid "Could not update site: %s"
msgstr ""

msgid "Site name"
msgstr ""

msgid "Language"
msgstr ""

msgid "Available languages"
msgstr ""

msgid "Region"
msgstr ""

msgid "Available regions"
msgstr ""

msgid "Cancel"
msgstr ""

msgid "Saving"
msgstr ""

msgid "Save changes"
msgstr ""

msgid "Edit title"
msgstr ""

msgid "Preview"
msgstr "Náhled"
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@
"dev": "concurrently npm:dev:*",
"dev:webpack": "webpack serve --config webpack/dev.config.js",
"dev:django": "python manage.py runserver_plus",
"msg:make": "python manage.py makemessages -l cs --ignore=venv --no-location",
"msg:compile": "python manage.py compilemessages --ignore=venv",
"msg:make": "concurrently npm:msg:make:*",
"msg:make:py": "python manage.py makemessages -l cs --no-location -i=venv ",
"msg:make:js": "python manage.py makemessages -l cs --no-location -i=venv -i=node_modules -d djangojs",
"msg:compile": "python manage.py compilemessages -i=venv",
"reqs": "concurrently npm:reqs:*",
"reqs:base": "pip-compile --resolver=backtracking --strip-extras --upgrade -o requirements.txt pyproject.toml",
"reqs:dev": "pip-compile --resolver=backtracking --strip-extras --upgrade --extra dev -o requirements/dev.txt pyproject.toml",
Expand Down
3 changes: 2 additions & 1 deletion tumbs/static/js/cms/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { useSelector } from "react-redux";
import { _ } from "./i18n";
import Alerts from "./components/Alerts";
import CreateWebsiteButton from "./components/CreateWebsiteButton";
import PageEditor from "./components/PageEditor";
Expand All @@ -20,7 +21,7 @@ const App = () => {
</>
) : (
<div className="d-flex flex-column justify-content-center align-items-center my-4">
<h4>No site yet</h4>
<h4>{_("No site yet")}</h4>
<CreateWebsiteButton />
</div>
)}
Expand Down
13 changes: 9 additions & 4 deletions tumbs/static/js/cms/components/CreateWebsiteButton.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { _, interpolate } from "../i18n";
import { actions as websitesActions } from "../slices/websites";
import { actions as alertsActions } from "../slices/alerts";
import { apiRequest } from "../network";
import { CURRENT_LANGUAGE } from "../store";
import Button from "react-bootstrap/Button";

const CreateWebsiteButton = () => {
Expand All @@ -14,14 +16,15 @@ const CreateWebsiteButton = () => {
setStatus("loading");
apiRequest("create_website", {
payload: {
name: "My New Site",
name: _("My New Site"),
language: CURRENT_LANGUAGE,
},
})
.then((website) => {
return apiRequest("create_page", {
payload: {
website_id: website.id,
title: "Homepage",
title: _("Homepage"),
},
}).then((page) => {
website.pages = [page];
Expand All @@ -32,7 +35,9 @@ const CreateWebsiteButton = () => {
})
.catch((err) => {
setStatus("error");
dispatch(alertsActions.addAlert({ content: `Could not create site: ${err}`, severity: "danger" }));
dispatch(
alertsActions.addAlert({ content: interpolate(_("Could not create site: %s"), err), severity: "danger" }),
);
// TODO: notify Sentry
});
};
Expand All @@ -45,7 +50,7 @@ const CreateWebsiteButton = () => {
<span className="bi bi-plus-circle" aria-hidden="true" />
)}
&ensp;
<span>Create Site</span>
<span>{_("Create Site")}</span>
</Button>
);
};
Expand Down
5 changes: 3 additions & 2 deletions tumbs/static/js/cms/components/SelectWebsite.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { _ } from "../i18n";
import { actions as websitesActions } from "../slices/websites";
import Form from "react-bootstrap/Form";

Expand All @@ -19,7 +20,7 @@ const SelectWebsite = () => {
<Form.Select
name="website"
value={currentWebsite.id}
aria-label="Available websites"
aria-label={_("Available websites")}
onChange={setCurrentWebsite}
>
{websites.map(({ id, name }) => (
Expand All @@ -31,7 +32,7 @@ const SelectWebsite = () => {
</Form.Group>
);
} else {
return <h3 className="mt-3 mb-3">No sites yet</h3>;
return <h3 className="mt-3 mb-3">{_("No sites yet")}</h3>;
}
};

Expand Down
25 changes: 14 additions & 11 deletions tumbs/static/js/cms/components/UpdateWebsiteModal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from "react";
import * as R from "ramda";
import { useSelector, useDispatch } from "react-redux";
import { _, interpolate } from "../i18n";
import { actions as alertsActions } from "../slices/alerts";
import { actions as updateWebsiteActions } from "../slices/updateWebsiteModal";
import { actions as websitesActions } from "../slices/websites";
Expand Down Expand Up @@ -37,7 +38,9 @@ const UpdateWebsiteModal = ({ website }) => {
})
.catch((err) => {
setStatus("error");
dispatch(alertsActions.addAlert({ content: `Could not update website: ${err}`, severity: "danger" }));
dispatch(
alertsActions.addAlert({ content: interpolate(_("Could not update site: %s"), err), severity: "danger" }),
);
// TODO: notify Sentry
hideModal();
});
Expand All @@ -52,40 +55,40 @@ const UpdateWebsiteModal = ({ website }) => {

<Modal.Body>
<Form.Group className="mb-3">
<Form.Label>Site name</Form.Label>
<Form.Label>{_("Site name")}</Form.Label>
<Form.Control
type="text"
name="name"
defaultValue={website.name}
required
disabled={isLoading}
placeholder="Site name"
placeholder={_("Site name")}
autoFocus
maxLength="255"
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Language</Form.Label>
<Form.Label>{_("Language")}</Form.Label>
<Form.Select
name="language"
defaultValue={website.language}
disabled={isLoading}
aria-label="Available languages"
aria-label={_("Available languages")}
>
{LANGUAGES.map(([code, name]) => (
<option value={code} key={code}>
{name}
{`${code.toUpperCase()} (${name})`}
</option>
))}
</Form.Select>
</Form.Group>
<Form.Group>
<Form.Label>Region</Form.Label>
<Form.Label>{_("Region")}</Form.Label>
<Form.Select
name="region"
defaultValue={website.region}
disabled={isLoading}
aria-label="Available regions"
aria-label={_("Available regions")}
>
{REGIONS.map(([code, name]) => (
<option value={code} key={code}>
Expand All @@ -100,19 +103,19 @@ const UpdateWebsiteModal = ({ website }) => {
<Button variant="secondary" disabled={isLoading} onClick={hideModal}>
<>
<i className="bi-x-circle" aria-hidden="true" />
&ensp;<span>Cancel</span>
&ensp;<span>{_("Cancel")}</span>
</>
</Button>
<Button type="submit" disabled={isLoading}>
{isLoading ? (
<>
<i className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
&ensp;<span>Saving</span>
&ensp;<span>{_("Saving")}</span>
</>
) : (
<>
<i className="bi-floppy" aria-hidden="true" />
&ensp;<span>Save changes</span>
&ensp;<span>{_("Save changes")}</span>
</>
)}
</Button>
Expand Down
25 changes: 19 additions & 6 deletions tumbs/static/js/cms/components/WebsiteNameEditor.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from "react";
import * as R from "ramda";
import { useDispatch } from "react-redux";
import { _, interpolate } from "../i18n";
import { actions as websitesActions } from "../slices/websites";
import { actions as alertsActions } from "../slices/alerts";
import { apiRequest } from "../network";
Expand Down Expand Up @@ -31,7 +32,9 @@ const WebsiteNameEditor = ({ website }) => {
})
.catch((err) => {
setStatus("error");
dispatch(alertsActions.addAlert({ content: `Could not update website: ${err}`, severity: "danger" }));
dispatch(
alertsActions.addAlert({ content: interpolate(_("Could not update site: %s"), err), severity: "danger" }),
);
// TODO: notify Sentry
});
};
Expand All @@ -46,21 +49,31 @@ const WebsiteNameEditor = ({ website }) => {
defaultValue={website.name}
disabled={isLoading}
autoFocus
placeholder="Site name"
aria-label="Site name"
placeholder={_("Site name")}
aria-label={_("Site name")}
/>
<Button variant="outline-secondary" disabled={isLoading} onClick={stopEditing}>
<Button variant="outline-secondary" disabled={isLoading} onClick={stopEditing} title={_("Cancel")}>
<i className="bi-x-circle" />
</Button>
<Button variant="outline-secondary" type="submit" disabled={isLoading}>
<Button
variant="outline-secondary"
type="submit"
disabled={isLoading}
title={isLoading ? _("Saving") : _("Save changes")}
>
{isLoading ? <i className="spinner-grow spinner-grow-sm" /> : <i className="bi-floppy text-success" />}
</Button>
</InputGroup>
</Form>
) : (
<>
<h3>{website.name}</h3>
<Button variant="light" onClick={startEditing} className="button-icon button-start-editing">
<Button
variant="light"
onClick={startEditing}
className="button-icon button-start-editing"
title={_("Edit title")}
>
<i className="bi-pencil" />
</Button>
</>
Expand Down
Loading

0 comments on commit 402beb7

Please sign in to comment.