{"id":15150362,"url":"https://github.com/trychlos/pwix-i18n","last_synced_at":"2026-02-09T18:31:24.367Z","repository":{"id":91959492,"uuid":"594470896","full_name":"trychlos/pwix-i18n","owner":"trychlos","description":"A Meteor internationalization package","archived":false,"fork":false,"pushed_at":"2025-07-01T17:19:01.000Z","size":295,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-01T18:27:41.902Z","etag":null,"topics":["i18n","internationalization","meteor","simple"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trychlos.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-28T16:50:49.000Z","updated_at":"2025-07-01T17:19:03.000Z","dependencies_parsed_at":"2024-09-13T02:32:39.306Z","dependency_job_id":"7580c744-4843-4af9-9b94-7d6281740a6c","html_url":"https://github.com/trychlos/pwix-i18n","commit_stats":{"total_commits":115,"total_committers":2,"mean_commits":57.5,"dds":"0.060869565217391286","last_synced_commit":"134ad6aa3f9b375818399cdd237a88986c0026d4"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/trychlos/pwix-i18n","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trychlos%2Fpwix-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trychlos%2Fpwix-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trychlos%2Fpwix-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trychlos%2Fpwix-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trychlos","download_url":"https://codeload.github.com/trychlos/pwix-i18n/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trychlos%2Fpwix-i18n/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269560931,"owners_count":24438216,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-09T02:00:10.424Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["i18n","internationalization","meteor","simple"],"created_at":"2024-09-26T14:02:45.926Z","updated_at":"2026-02-09T18:31:24.338Z","avatar_url":"https://github.com/trychlos.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pwix:i18n\n\n## What is it ?\n\nYet another very simple package to handle internationalization in Meteor, light and easy.\n\nAims to works both on client and server sides.\n\n## Installation\n\nThis Meteor package is installable with the usual command:\n\n```sh\n    meteor add pwix:i18n\n```\n\n## Usage\n\nVery simple:\n\n```js\n    import { pwixI18n } from 'meteor/pwix:i18n';\n\n    import './myapp.i18n.de.js';\n    import './myapp.i18n.en_GB.js';\n    import './myapp.i18n.en-US.js';\n    import './myapp.i18n.fr.js';\n\n    const key = 'my.key';\n    console.log( 'language='+i18n.language(), 'key='+key, 'translated='+i18n.label( myapp.i18n, key ));\n```\n\nor more advanced:\n\n```js\n    import { pwixI18n as i18n } from 'meteor/pwix:i18n';\n\n    import './myapp.i18n.de.js';\n    import './myapp.i18n.en_GB.js';\n    import './myapp.i18n.en-US.js';\n    import './myapp.i18n.fr.js';\n\n    i18n.configure({\n        language: 'fr',\n        namespace: 'my_namespace',\n        translations: myapp.i18n\n    });\n\n    const key = 'my.key';\n    console.log( 'language='+i18n.language(), 'key='+key, 'translated='+i18n.label( 'my_namespace', key ));\n```\n\n## Translation management\n\n### Language identification\n\nAs far as `pwix:i18n` is concerned, the way you name your translations is - generally speaking - without any importance. More, if you are writing a somewhat relatively big package or application, you will have to deal with other packages, which each will have their own way to name their translations.\n\nNonetheless, and besides of quasi universal usages, some sort of normalization has been set up by the [Internet Engineering Task Force](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force) (IETF) in its [IETF BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag)\n\nRegarding the `-` _vs_ `_` debate, the Unicode specifications, in its 3rd [Unicode Language and Locale Identifiers](https://unicode.org/reports/tr35/tr35.html#Unicode_Language_and_Locale_Identifiers) chapter, clearly states that dash and underscore separators must be treated as equivalent.\n\nThe two flavors are quasi universally found: 'en-US' (dash-separated) and 'en_US' (underscore-separated), each being widely used in its own domain (e.g. Unix world is used to use 'en_US' for naming its locales, while PHP developers for example are more easy with 'en-US').\n\nWe make our best to be compliant with both versions.\n\nSome useful links:\n\n- [Internet Engineering Task Force on Wikipedia](https://en.wikipedia.org/wiki/Internet_Engineering_Task_Force)\n- The [IETF](https://www.ietf.org/) itself\n- [BCP 47 links on W3C](https://www.w3.org/International/core/langtags/rfc3066bis.html)\n\n### Translations object\n\nThe available translations, whether for an application or a package, must obviously be explicitely provided to the `pwix:i18n` package. This is done through a standard Javascript object, with the simple structure :\n\n- first key level is the language identifier\n- second level and followings are up to the developer\n- final value (the leaf) is the translated string.\n\nThe translated string can be a [`printf()`](https://www.npmjs.com/package/printf) format specification.\n\nExample:\n\n```js\n    {\n        de: {\n            ...\n        }\n        en_US: {\n            first: {\n                second: {\n                    third: \"this translated string is adressed with the 'first.second.third' key\"\n                }\n            },\n            another: \"this one string with the 'another' key\"\n        }\n    }\n```\n\nBut NOT:\n\n```js\n    {\n        de: {\n            ...\n        }\n        en_US: {\n            'first.second.third': \"pwixI18n doesn't manage this structure; you have to use another separator than the dot '.'\"\n            another: \"this one string with the 'another' key\"\n        }\n    }\n```\n\nAt least the second level is required, i.e. the `first` and `another` ones in this example.\n\nThe translated string can be an array of strings when the developer wishes use an array:\n\n```js\n    {\n        fr: {\n            first: {\n                second: [\n                    \"first translated string\",\n                    \"second string\",\n                    \"third string\",\n                    ...\n                ]\n            }\n        }\n    }\n```\nIn this case, the `label()` method will return the array itself.\n\n### Translations namespace\n\nIf all your translated strings are in a single data structure as a well-formed translations object, which may be the case for example for a small package or a small application, then you can just provide this single object to each method which expects a translations object.\n\nContrarily, if you get an object per language, and do not care of aggregating them in a single translations object, then you can ask to `pwix:i18n` to allocate a namespace for you, and manage it.\n\nAs a convenience for the developer, `pwix:i18n` methods accept a namespace string each time a translations object is expected.\n\nExample, in an application:\n\n```js\n    pwixI18n.set( \u003cmy_application_namespace\u003e, \u003cmy_translations_object\u003e );\n    pwixI18n.label( \u003cmy_application_namespace\u003e, \u003cmy.key\u003e );\n```\n\nor\n\n```js\n    pwixI18n.label( \u003cmy_translations_object\u003e, \u003cmy.key\u003e );\n```\n\nor\n\n```js\n    pwixI18n.set( \u003cmy_application_namespace\u003e, \u003clanguage_a\u003e, \u003cmy_translations_object_a\u003e );\n    pwixI18n.set( \u003cmy_application_namespace\u003e, \u003clanguage_b\u003e, \u003cmy_translations_object_b\u003e );\n    pwixI18n.label( \u003cmy_application_namespace\u003e, \u003cmy.key\u003e );\n```\n\nMost of the time, the application namespace will be just the name of the application, the package namespace will be just the name of the package. But entirely your choice.\n\nWhich one of these flavors will you choose mostly depends if you have chosen to have one object per language (at most), or one single object for all your managed translations. Maybe installing a namespace for a single one-object-all-translations is one call too much.\n\n## Provides\n\n### `pwixI18n`\n\nThe exported `pwixI18n` global object provides following items:\n\n#### Functions\n\n##### `pwixI18n.date( stamp )`\n##### `pwixI18n.date({ format: \u003cformat\u003e, language: \u003clanguage\u003e, stamp: \u003cstamp\u003e })`\n\nReturns the date only formatted according to current `pwix:i18n` configuration, with:\n\n- `stamp` is the Date object to be rendered\n- `language` defaults to currently configured language\n- `format` defaults to configured date style, according to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)\n\n##### `pwixI18n.dateTime( stamp [, language] )`\n##### `pwixI18n.dateTime({ format: \u003cformat\u003e, language: \u003clanguage\u003e, stamp: \u003cstamp\u003e })`\n\nReturns the stamp formatted according to current `pwix:i18n` configuration, with:\n\n- `stamp` is the Date object to be rendered\n- `language` defaults to currently configured language\n- `format` defaults to configured date and time styles, according to [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)\n\n##### `pwixI18n.defaultLanguage()`\n\nReturns the default language which has been automatically computed at startup.\n\nThis has nothing to do with the language set via the `pwixI18n.configure()` method. Rather this is the default value computed by the package if no language at all is configured.\n\n##### `pwixI18n.defaultLocale()`\n\nReturns the current default locale for this runtime environment, as best as we can guess...\n\n##### `pwixI18n.group( namespace, key )`\n\nReturns the specified content.\n\nMay be useful when the translation file contains for example an array of strings...\n\n##### `pwixI18n.label( namespace|translations_object, key, ... )`\n\nReturns the localized string.\n\nWhen supplementary arguments are provided, they are used according to the standard `printf()` specifications.\n\nBecause it depends of `pwixI18n.language()` reactive data source, it is itself able to react to language changes.\n\n##### `pwixI18n.labelEx()`\n\nAn extension of the previous `pwixI18n.label` which also returns the localized string.\n\nDifferences is that this method takes arguments as a single object, with:\n\n- name: mandatory, either a namespace or a translations object,\n- key: mandatory, the name of the to-be-translated string\n- language, optional, the language identifier, defaulting to the current language.\n\nLetting the language be specified, this method allows the caller to ask for a translation different from the current one.\n\nWhen additional arguments are provided, they are used according to the standard `printf()` specifications.\n\n##### `pwixI18n.langEnumerate( language, cb )`\n\nThis method will call the provided `cb` callback with each to-be-tested language, starting with the provided identifer.\n\nThe callback may return `false` to stop the enumeration.\n\nExample:\n- if language='en_US', the callback will be successively called with 'en-US' and 'en' languages.\n\nThis is not a typo: internally `pwix:i18n` replaces underscores with hyphens, and so will be triggered the callback.\n\nCallback prototype is `cb( language )`.\n\n##### `pwixI18n.language( [language] )`\n\nAs a getter, returns the configured language, making sure it is not null, defaulting to hardcoded default language.\n\nA reactive data source.\n\nAs a setter, configure the desired language.\n\n##### `pwixI18n.namespace( namespace, translations_object )`\n##### `pwixI18n.namespace( namespace, language, keyed_translated_strings )`\n##### `pwixI18n.namespace({ language: \u003clanguage\u003e, namespace: \u003cnamespace\u003e, translations: \u003ctranslations_object\u003e })`\n\nSetup the managed translations for this namespace.\n\n- in the first form, `language` is not specified, it is then expected that the `translations_object` is a standard translation object as described above,\n  i.e an object keyed by language identifier(s), where values are keyed translated strings for these languages\n\n- in the second form, with a specified `language`, then it is expected that `keyed_translated_strings` is just an object with keyed strings, without the language identifier level.\n\n- the third accepted form accepts these same arguments inside of a single object, the `translations` key providing either a translation object or keyed translated strings depending of wether a `language` key is specified or not\n\nSuccessive calls are additive: successively provided translations objects are added to the same namespace.\n\n#### Constants\n\n##### Label position\n\n    - `pwixI18n.C.BtnLabel.NONE`\n    - `pwixI18n.C.BtnLabel.LEFT`\n    - `pwixI18n.C.BtnLabel.ABOVE`\n    - `pwixI18n.C.BtnLabel.RIGHT`\n    - `pwixI18n.C.BtnLabel.BELOW`\n\n##### Hardcoded default language\n\n    - `pwixI18n.C.Defaults.language`\n\n##### Verbosity levels\n\n    - `pwixI18n.C.Verbose.NONE`\n    - `pwixI18n.C.Verbose.CONFIGURE`\n    - `pwixI18n.C.Verbose.COMPONENTS`\n    - `pwixI18n.C.Verbose.LANGUAGE`\n\n##### `pwixI18n.btnLabelPosition`\n\nThe known positions of the label in the `piLanguageSelector` component, as an array.\n\n### Blaze components\n\n#### `piLanguageSelector`\n\nA simple language selector, built as a Bootstrap dropdown\n\n- An example of the dropdown button with default english\n\n    ![dropdown button](/maintainer/png/english-dropdown.png)\n\n- An example of the opened menu with two languages\n\n    ![Example of the opened menu with two languages](/maintainer/png/opened-menu.png)\n\nThe component is configurable with an object passed as an argument, which may contain:\n\n- `languages`\n\n    An array of the languages to be displayed as dropdown items, defaulting to the single default language (`[ 'en' ]`).\n\n    The provided array should at least include the default `pwixI18n.C.Defaults.language` language.\n\n- `buttonFlag`\n\n    Whether the country flag icon should be displayed in the dropdown menu button, defaulting to `true`.\n\n- `buttonLabel`\n\n    Where the language label should be displayed in the dropdown menu button, defaulting to `pwixI18n.C.BtnLabel.NONE`.\n\n    Possible values are those recorded in `pwixI18n.btnLabelPosition` reference array.\n\n- `itemsFlag`\n\n    Whether the country flag icon should be displayed in the dropdown items, defaulting to `true`.\n\n- `itemsLabel`\n\n    Whether the language label should be displayed in the dropdown items, defaulting to `true`.\n\n- `disableActive`\n\n    Whether to disable the currently active item, defaulting to `true`.\n\n### Blaze helper\n\n#### `_`\n\nExample:\n\n```html\n    {{_ namespace key }}\n```\n\nObviously only available on the client.\n\n## Configuration\n\nThe package's behavior can be configured through a call to the `pwixI18n.configure()` method, with just a single javascript object argument, which itself should only contains the options you want override.\n\nKnown configuration options are:\n\n- `dateStyle`\n\n    The way dates must be displayed, defaulting to `short`.\n\n    See [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) for a specification reference.\n\n- `language`\n\n    The chosen language.\n\n    If not explicitly configured, `pwix:i18n` makes its best to provide a suitable default:\n\n    - if a previously chosen language has been stored on the local device, and the user has allowed the user of _cookies_ (if anyone has asked him), then use it (please note that this local storage is user-independant and device-only),\n\n    - else use the language provided by the `pwixI18n.defaultLocale()` method,\n\n    - else use the hardcoded `pwixI18n.C.Defaults.language`.\n\n    In all cases, the language may also be defined later via the `pwixI18n.language()` method.\n\n    A word of caution: if you, as an application developer, configure here a particular language, you are actually overriding the above default computing. So be sure of knowing what you do.\n\n- `managed`\n\n    An array of languages that the application is willing to manage.\n\n    Default to just (`[ 'en' ]`).\n\n- `storePreferredLanguage`\n\n    Whether the application plans to let the user choose his preferred language, and store this preference as a local data.\n\n    When enabled, this option will create a _cookie_, that the user may refuse.\n\n    Default to `true`.\n\n- `timeStyle`\n\n    The way times must be displayed, defaulting to `medium`.\n\n    See [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) for a specification reference.\n\n- `verbosity`\n\n    Define the expected verbosity level.\n\n    The accepted value can be any or-ed combination of following:\n\n    - `pwixI18n.C.Verbose.NONE`\n\n        Do not display any trace log to the console\n\n    - `pwixI18n.C.Verbose.COMPONENTS`\n\n        Trace Blaze components life:\n\n        - creation\n        - rendering\n        - destruction\n\n    - `pwixI18n.C.Verbose.CONFIGURE`\n\n        Trace `pwixI18n.configure()` calls and their result\n\n    - `pwixI18n.C.Verbose.DUMP`\n\n        Dump the `pwixI18n` global object at startup.\n\n    - `pwixI18n.C.Verbose.LANGUAGE`\n\n        Trace language computings.\n\nPlease note that `pwixI18n.configure()` method should be called in the same terms both in client and server sides.\n\nAlso note, as an explicit reminder for the fools, that, because the Meteor packages are instanciated at application level, they can be configured once at most, and only once at most. Each addtionnal call to `pwixI18n.configure()` will just override the previous one. You have been warned: **only the application should configure a package**.\n\n## NPM peer dependencies\n\nStarting with v 1.1.0, and in accordance with advices from [the Meteor Guide](https://guide.meteor.com/writing-atmosphere-packages.html#peer-npm-dependencies), we no more hardcode NPM dependencies in the `Npm.depends` clause of the `package.js`.\n\nInstead we check npm versions of installed packages at runtime, on server startup, in development environment.\n\nDependencies as of v 1.5.0:\n\n```js\n    'bootstrap': '^5.2',\n    'lodash': '^4.17.0',\n    '@popperjs/core': '^2.11.6',\n    'printf': '^0.6.1'\n```\n\n## Translations\n\nNew and updated translations are willingly accepted, and more than welcome. Just be kind enough to submit a PR on the [Github repository](https://github.com/trychlos/pwix-i18n/pulls).\n\n## Cookies and comparable technologies\n\n`pwix:i18n` may use `localStorage` to record some valuable data.\n\n### `pwix:i18n/preferred_language`\n\nThe last chosen language.\n\nAllowed/disallowed through the `storePreferredLanguage` configuration parameter.\n\nThis is considered a disableable functional _cookie_, and is advertised as such to the CookieManager if present.\n\n## Issues \u0026 help\n\nIn case of support or error, please report your issue request to our [Issues tracker](https://github.com/trychlos/pwix-i18n/issues).\n\n---\nP. Wieser\n- Last updated on 2025, Jul. 7th","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrychlos%2Fpwix-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrychlos%2Fpwix-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrychlos%2Fpwix-i18n/lists"}