Technical design: static text localization and internationalization in 3.x
See original GitHub issueThis issue concerns static text. For editable content localization see:
https://github.com/apostrophecms/apostrophe/issues/3205
The proposal we have arrived at internally is as follows, with additional details describing the process for shipping JSON files:
-
Use the
i18next
npm module server side, with namespaces. Specifically all Apostrophe phrases will be in the apostrophe namespace, regardless of origin. This keeps admin phrases separate from project level phrases. -
Use the middleware support of i18next, and also inject a function to get the benefit of this in templates.
-
Push all of the apostrophe namespace phrases to the front end, via
getBrowserOptions
of the@apostrophecms/ui
module, and configurevue-i18next
with them. -
Other apostrophe modules making up our UI will have to wait for i18next to initialize or they might not produce sensible output at startup. So we need to add a convention to control the order in which apostrophe’s frontend js apps (found in
ui/apos/apps
folders) are started so we don’t have to do a lot of listening on the bus. We will do this with a bit of new syntax. Rather than exporting a function, apps (like ApostropheI18nNext or ApostropheAdminBar) can export an object:
export default {
priority: 1000,
app() { ... }
}
Any app that exports just a function is considered to have a priority of 0. Then apps will be initialized in priority order, highest priority first. Initially it is expected that the only app needing to explicitly use this mechanism will be the app in the ui
module that initializes vue-i18next
.
i18n syntax examples
EXPRESS
We will use the i18next-http-middleware
so we can write:
req.t('myKey', { ns: 'apostrophe' })
… Anytime we want to do this directly rather than in Nunjucks. If ns
is not specified the default namespace is the project level one.
NUNJUCKS
We will inject a function that wraps req.t
so that we can write:
{# apostrophe UI static text #}
{{ __t('myKey', { ns: 'apostrophe' }) {{
{# project level static text #}
{{ __t('myKey') }}
VUE
Via vue-i18next
we will be able to write this in any Apostrophe admin UI Vue component:
{{ $t('myKey') }}
In browerspace the default namespace is apostrophe.
ui/src javascript
For now only ui/apos Vue components will have access to i18next phrases on the browser side. Support for access to i18next phrases in ui/src javascript may be added at a later time.
Other Modules, Other Namespaces
Additional npm modules providing add-on Apostrophe UI will need to be able to use their own namespaces, while still participating on the browser side. To address this, any module may set its own i18nNamespace
option, like so:
options: {
i18next: {
ns: 'my-custom-namespace',
browser: true
}
If browser: true
is not passed then the phrases are only available server-side.
Special considerations for pieces
All piece types need their own labels, distinct from other piece types. So {{ __t(‘label’) }} would not be a good solution in a Vue template as there can only be one i18next phrase with the key label
. Instead, these labels will be localized server-side via req.t
and made available via getBrowserData
to the individual module as they already are today.
Keys versus default English text phrases
Apostrophe will ship with keys in i18next calls, rather than “default English” text phrases.
That is, a Vue component might contain: {{ $t('toggleSelectionOf', { label: this.label })
Shipping JSON files: Apostrophe core
The apostrophe core module and other apos UI npm modules will ship with JSON files in i18next JSON format, version 3.
These will ship in a locales
subdirectory of the @apostrophecms/ui
module, for the apostrophe
namespace, and in other modules that choose to have i18next namespaces.
Within locales
files we will follow the i18next version 3 format. For example, modules/@apostrophecms/ui/locales/en.json
will contain:
{
"toggleSelectionOf": "Toggle selection of {{ label }}"
}
Our intention is to add additional JSON files over time for other languages and locales. We welcome contributions to this project.
Shipping JSON files: other npm modules
Other npm modules that set the i18next
option may also ship with a locales
folder, which will automatically be loaded.
Shipping JSON files: project-level code
The project-level default i18next namespace, which is currently never pushed to browser-side JavaScript but is available for server-side localization in Nunjucks templates etc., can be populated by creating a locales
folder at the root of the project.
Interactive Editing
It is our intention to eventually ship a module similar in functionality to the 2.x apostrophe-i18n-static
module, which provided the ability to edit the translation of static text phrases as pieces in the Apostrophe UI. This will supplement the JSON support rather than replacing it altogether.
Distinct admin and project-level locales
In some cases, users with editing privileges may wish to view project-level static text in a selected locale without also translating apostrophe admin UI, even though translations are available. This is an enterprise requirement that has come up in the past. With a growing set of translations available it will essentially be necessary to support this feature, however this will arrive in a later phase of development. Initially, setting the locale to fr-fr
will impact both the admin UI and the project level static text, assuming translations exist.
Issue Analytics
- State:
- Created 2 years ago
- Comments:13 (13 by maintainers)
Top GitHub Comments
l10n
is a standard and sounds like a candidate for folder containing the… l10n 😃I was a contributor at Mozilla (translated the entire Mozilla and Firefox website in Bulgarian) few years ago. I can give you feedback about what challenges Mozilla had with l10n, how they were solving them in terms of tooling and what went wrong (while I was around).
And of course count me in for translation of the core in Bulgarian.
a8e, matey!
On Tue, Jul 13, 2021 at 6:30 AM Miro Yovchev @.***> wrote:
–
THOMAS BOUTELL | CHIEF TECHNOLOGY OFFICER APOSTROPHECMS | apostrophecms.com | he/him/his