i18n / Localization¶
Status: Audit v0.1 (2026-05-09).
1. Status¶
The web client has no internationalisation infrastructure.
| Tool | Wired? | Source |
|---|---|---|
vue-i18n |
No | Not in package.json |
@nuxtjs/i18n |
No | Same |
react-intl, lingui, i18next |
No | Same |
| Translation files (JSON / YAML) | No | No locales/ or translations/ directory |
| Translation management system | No | No Lokalise / Crowdin / Transifex config |
grep -rE "vue-i18n\|@nuxtjs/i18n" package.json polotno-editor/package.json returns no matches.
All UI strings are hardcoded English in .vue template blocks and JS string literals.
2. Backend-supplied locale data¶
The backend does provide a /getLanguages endpoint (cached via api/fetchLanguages in store/api.js). This returns a list of languages — likely for content language selection (the user's posts can be in different languages), not for UI locale.
grep -nE "getLanguages\|languagesCache" store middleware 2>/dev/null confirms it's about post content, not UI.
[VERIFY-I18N-1]: confirm with the team that /getLanguages is content-language only, not UI-translation.
3. Tone of voice¶
Similar — getToneOfVoice returns content-tone presets ("formal", "casual", etc.) for AI generation, not UI locale.
4. Date / number / currency formatting¶
| Concern | Status |
|---|---|
| Dates | moment + moment-timezone are used heavily; moment(...).format('...') calls are English-formatted by default. moment.locale(...) could switch but there are no observed moment.locale calls. |
| Numbers | helpers/helper.js → formatMetrics and commaSeparatedNumber use n.toLocaleString() for the small case but hard-coded K/M/B/T suffixes (English). Other locales would need Intl.NumberFormat with compactDisplay. |
| Currency | Stripe / Paddle handle their own currency formatting in their UI widgets. The web client itself has no currency-formatting helper observed. |
Finding [WC-I18N-1] (Severity: Medium): Number / date formatting is locale-naive. Even without UI translation, formatting numbers as 1,234,567.89 (US) for a German user is wrong (1.234.567,89). Pure-Intl adoption is feasible without full i18n.
5. RTL languages¶
No RTL CSS support observed:
grep -rE "\[dir=\"rtl\"\]\|direction:\s*rtl" assets pages components 2>/dev/null
# (likely empty — verify)
Adding Arabic / Hebrew support would require:
- RTL stylesheet (
bootstrap-rtlor BS5'srtlbuild). - Logical CSS properties (
margin-inline-startinstead ofmargin-left) — currently using BS4-eramr-2/ml-2classes which are not RTL-aware. - A direction-switcher tied to locale.
This is a Phase 2+ effort if internationalisation is on the roadmap.
6. Implications for enterprise customers¶
Enterprise B2B customers — especially those in Europe, the Middle East, or APAC — frequently require:
- At minimum: locale-aware date/number formatting.
- Often: UI translation for the languages of their users.
- Sometimes: contractually mandated WCAG + locale support.
The current state means the web client cannot be sold "as-is" to a non-English-first market. Verify with the team whether the product strategy targets non-English markets in the next 12 months.
7. Recommendations¶
Phase 1 (if internationalisation is on the roadmap)¶
- Adopt
vue-i18n@8(Vue 2 compatible) or@nuxtjs/i18n@7. - Sweep all UI strings into
locales/en.json. This is the bulk effort — likely 1–2 weeks for the 159K LOC, given the level of inline strings. - Connect to a TMS (Lokalise or Crowdin).
- Add
Intl.NumberFormat/Intl.DateTimeFormathelpers tohelpers/helper.js; deprecate moment's English-locked formatting.
Phase 2¶
- Add second locale (likely Spanish or French based on customer geography — verify).
- RTL support if Arabic/Hebrew are targeted.
Phase 3¶
- Continue rollout to more locales as customer demand materialises.
8. Open questions¶
Tracked in ./verify-markers.md:
- [VERIFY-I18N-1] Confirm
/getLanguagesis content-language only - [VERIFY-I18N-2] Is internationalisation on the product roadmap?