Skip to content

Repository files navigation

vue-i18n-python

An unofficial Python port of vue-i18n. Not affiliated with or endorsed by intlify; vue-i18n is © kazuya kawaguchi and contributors, MIT licensed.

Same JSON message files, same API, same behaviour — in Python. The point is a Vue front end and a Python back end reading one set of translations and producing the same strings from them.

import json

from vue_i18n import create_core_context, translate

ctx = create_core_context(
    locale="sl",
    fallback_locale="en",
    messages={                                     # the files your front end already loads
        "sl": json.load(open("locales/sl.json")),
        "en": json.load(open("locales/en.json")),
    },
)

translate(ctx, "hello", {"name": "Jure"})          # 'Zdravo Jure'
translate(ctx, "trips", 5)                         # plural form for 5

docs.velis.si/vue-i18n-python is the manual.

Why this exists, and who should not use it Rationale
Installing it and the call shapes Getting started
The one thing that surprises people Plural rules
Where it deliberately differs from vue-i18n Differences
Every public function API reference

Message files are ordinary vue-i18n resources: {named} placeholders, {0} positional values, a | b | c plurals, @:linked messages, @.upper: modifiers, {'@'} literals. Nothing asks you to migrate a file or learn a syntax, and vue-i18n-extract and the rest of the toolchain keep working.

Option names are vue-i18n's, in snake_case: fallbackLocale is fallback_locale, missingWarn is missing_warn.

Checking what you wrote

t("cart.emty") does not fail — it renders the key and waits for a customer to find it. The bundled checker finds it first, on both ends of the project:

python -m vue_i18n.check locales/ --source backend/ --source frontend/src

Broken @:links, messages that will not compile, keys one locale is missing, keys the code asks for and no locale has. Python is parsed; .vue and .ts are pattern-matched, which is approximate and labelled so — and still more than xgettext, which cannot open a .vue file at all.

How faithful is it?

Faithful enough that the claim is checked rather than asserted. Every part of the port is recorded against the real thing and replayed on every test run:

corpus what it pins
conformance/translate.json 57 translate() calls against @intlify/core-base itself
conformance/render.json 74 messages rendered by real vue-i18n
conformance/compile.json 128 messages: ASTs, error codes, error messages, source locations
conformance/resolve.json 200 key-path resolutions
conformance/fallback.json 374 fallback chains
conformance/display.json 1612 values through JavaScript's String() semantics

The recordings are generated by running upstream, never written by hand — scripts/conformance/README.md says how to regenerate them.

Following upstream

This port tracks vue-i18n's released versions, never a pre-release. Upstream is a git submodule pinned to the version being tracked, so "which vue-i18n does this match" is answered by a checkout rather than by a claim. UPSTREAM.md records the pin, maps every module to the upstream file it came from, and holds the procedure for moving to a new release.

Where it differs

Some differences are forced by the platform: JavaScript strings are UTF-16 and Python's are not, Intl does not exist here so d() and n() go through babel with different CLDR data, and a Python int stays exact past 2^53.

Others are chosen, and each one is written down in PROGRESS.md with the reasoning, a comment at the site and a test that asserts it. GAPS.md lists what is knowingly missing.

Plural rules

If your Vue application already passes pluralRules to createI18n, pass the same rule here and nothing changes. A rule is (choice, choices_length) -> index, the same signature as in JavaScript, so it transcribes directly:

def south_slavic(choice, choices_length, _org=None):
    if choices_length == 2:
        return 0 if choice == 1 else 1
    ...

ctx = create_core_context(..., plural_rules={"sl": south_slavic})
translate(ctx, "trips", 103)     # '103 povezave' - the fourth form, as in the browser

If you pass no rule, you get vue-i18n's default, and that default ignores the locale: two forms mean singular/plural, and anything more clamps at index 2, so a fourth or fifth form is unreachable in any language. This port reproduces that rather than quietly improving on it — the same message with no rule renders 3 povezavi, 5 povezavi and 105 povezavi — the count interpolates, the ending is what sticks — here and in the browser alike.

vue_i18n.plurals is there if you would rather not hand-write the rule. It is opt-in; the runtime never reaches for it. It carries CLDR rules for 224 locales, an explicit zero form that CLDR does not have, and a ladder for messages with fewer forms than the locale has categories. Note that it will not agree with a hand-written rule in every case — if your front end has one, port that one, and keep the two ends identical.

Status

Early, and honest about it — see PROGRESS.md for what exists and GAPS.md for what does not.

License

MIT

About

vue-i18n, in Python

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages