Skip to content

Take the application's t function and expose one translate() - #1

Merged
velis74 merged 4 commits into
mainfrom
live-translations
Oct 7, 2026
Merged

velis74 merged 4 commits into
mainfrom
live-translations

Conversation

@velis74

@velis74 velis74 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Problem

translateStrings(cb) called cb once for every key and stored the results, so a callback built on vue-i18n froze every string in the locale active at the call. An application that starts in the browser's locale and switches to the user's saved one keeps the library strings in the first locale.

The callback also had to return the raw template for the library to interpolate, and vue-i18n has no reliable way to give one: t() substitutes placeholders with empty strings when it is not given params, and tm() returns compiled functions instead of text once messages are compiled at build time.

Keys that only exist at run time, such as error codes defined by an application's backend, could not be translated at all: the key set was fixed by createTranslatable.

Change

  • translateStrings(t, namespace?) takes the application's translation function, shaped like vue-i18n's and i18next's t: (key, named) => string, returning the key unchanged when there is no translation. The library calls it as t('forms.MinValue', { minValue: 5 }) with its own values, so the i18n library does the interpolation and no raw template is needed. A key returned unchanged falls back to the library's English default, after the fallback locales t itself consults.
  • translate(key, params?, defaultValue?) is the one way a library reads a string, declared or not. It is reactive wherever it is read, as t is: a template, a computed, a watcher. A run-time key falls back to defaultValue, then to the key.
  • Removed: strings, lookup, the free translate(strings, key, params) and TranslateStringsCallback. strings.X cannot survive the change: for a string with placeholders it would have to call t without params, which erases them.

Version 0.2.0, since the public API changes. vue-forms, vuetify-inputs, vue-grid and fastapi-viewsets move to translate(key, params) and re-export the new translateStrings in their own releases.

Usage in an application

translateFormsStrings(i18n.global.t, 'forms');
translateGridStrings(i18n.global.t, 'grid');

Test plan

  • npm test: 16 tests against a real vue-i18n 11 (dev dependency only): translation with params substituted by t, fallback locale, English default for a missing key, locale switch updating a computed and re-running an effect the way a render does, re-passing the same function over non-reactive translations, run-time keys with and without a default, 100% coverage
  • npm run lint:ci: vue-tsc accepts i18n.global.t from createI18n with inferred message types as a TranslateFunction
  • npm run build

translateStrings keeps its callback and every entry of strings is a computed over
it, so a callback that reads vue-i18n's locale updates every string on a locale
switch. The callback also receives the string's placeholders, to pass to an
interpolating lookup that would otherwise substitute them with nothing, and
lookup() resolves keys that only exist at run time through the same callback.
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

✅ Incremental coverage — 100%

████████████████████ 15 / 15 changed lines covered · threshold 70% · main → live-translations

File Coverage Covered Uncovered lines
✅ src/translatable.ts 100% 15 / 15 —
Total 100% 15 / 15
6 files not graded (2 ignored by pattern, 4 not source files)
File Reason
changelog.md not a source file
package-lock.json not a source file
package.json not a source file
readme.md not a source file
src/index.ts ignored by **/index.ts
src/translatable.spec.ts ignored by *.spec.*

Coverage reports: coverage/coverage-final.json (istanbul, 1 file) — incremental-coverage-check v3.0.0

vue-i18n's tm() already returns the raw message, resolved through the fallback
locale, so the callback needs no third argument to survive t()'s interpolation.
translateStrings(t, namespace) takes a function shaped like vue-i18n's t and
calls it with the library's own params, so the i18n library substitutes the
placeholders and a key it returns unchanged falls back to the English default.
translate(key, params, defaultValue) replaces strings, lookup and the free
translate() for declared and run-time keys alike.
@velis74 velis74 changed the title Resolve translations lazily so strings follow a reactive locale Take the application's t function and expose one translate() Oct 6, 2026
@velis74
velis74 merged commit 5338895 into main Oct 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant