{"id":32231635,"url":"https://github.com/tabone/i18n","last_synced_at":"2026-02-27T12:10:40.520Z","repository":{"id":31782128,"uuid":"35348534","full_name":"tabone/i18n","owner":"tabone","description":"Lightweight NodeJS Internationalization  Module.","archived":false,"fork":false,"pushed_at":"2017-12-06T22:20:49.000Z","size":69,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-23T05:46:33.818Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tabone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-09T22:54:13.000Z","updated_at":"2017-01-24T22:08:34.000Z","dependencies_parsed_at":"2022-09-05T00:01:39.535Z","dependency_job_id":null,"html_url":"https://github.com/tabone/i18n","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/tabone/i18n","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabone%2Fi18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabone%2Fi18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabone%2Fi18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabone%2Fi18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tabone","download_url":"https://codeload.github.com/tabone/i18n/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabone%2Fi18n/sbom","scorecard":{"id":865140,"data":{"date":"2025-08-18","repo":{"name":"github.com/tabone/i18n","commit":"bbc18b41c3cc014cc9f117c52f20887d73a7e4ae"},"scorecard":{"version":"v5.2.1-41-g40576783","commit":"40576783fda6698350fcbbeaea760ff827433034"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 2/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/40576783fda6698350fcbbeaea760ff827433034/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T02:29:28.639Z","repository_id":31782128,"created_at":"2025-08-24T02:29:28.639Z","updated_at":"2025-08-24T02:29:28.639Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29893922,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T12:09:13.686Z","status":"ssl_error","status_checked_at":"2026-02-27T12:09:13.282Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2025-10-22T11:44:08.513Z","updated_at":"2026-02-27T12:10:37.556Z","avatar_url":"https://github.com/tabone.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/tabone/i18n.svg?branch=master)](https://travis-ci.org/tabone/i18n)\n[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)\n[![Coverage Status](https://coveralls.io/repos/tabone/i18n/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/tabone/i18n?branch=master)\n\n# i18n-light\n\n## Installation\n\n```bash\nnpm install --save i18n-light\n```\n\n```bash\nbower install --save i18n-light\n```\n\n## Motiviation\nMy main motivation in developing `i18n-light` was to create a localization module which enabled a developer to use the same storage (`dictionaries`) for both `Back-end` and `Front-end` code, thus having localized phrases more consistent and organized.\n\n## Vocabulary\n| Name | Description |\n|------|-------------|\n| `Dictionary` | A `JSON file` which `i18n-light` will use for localization. |\n| `Dicionary Contexts` | Is the `JSON` of a locale. This reside within a `dictionary` and is this `Object` which `i18n-light` will be using for localization. |\n| `Dictionary Path` | Is the path which i18n-light need to travel through the `dictionary context`. |\n| `Locale` | A name for a dictionary. |\n\n## Usage\n### Structure\n```\n  app\n  ├── dict/\n  |   ├── en.json\n  |   └── it.json\n  └── server.js\n```\n\n### Dictionaries\n#### dict/en.json\n\n```javascript\n{\n  \"common\": {\n    \"logo\": \"i18n-light\"\n  },\n  \"home\": {\n    \"logout\": \"Logout\",\n    \"loggedin\": \"Hello %s\",\n    \"messages\": {\n      \"zero\": \"No messages\",\n      \"one\": \"1 message\",\n      \"many\": \"%s messages\"\n    }\n  }\n}\n```\n#### dict/it.json\n\n```javascript\n{\n  \"home\": {\n    \"logout\": \"Esci\",\n    \"loggedin\": \"Ciao %s\",\n    \"messages\": {\n      \"zero\": \"0 messaggi\",\n      \"one\": \"1 messaggio\",\n      \"many\": \"%s messaggi\"\n    }\n  }\n}\n```\n\n### Basic Example\n\n```javascript\nvar i18n = require('i18n-light')\n\ni18n.configure({\n  defaultLocale: 'en',\n  dir: path.join(__dirname, 'dict'),\n  extension: '.json'\n})\n```\n\n### Express Example\n\n```javascript\nvar express = require('express')\n  , app = express()\n  , i18n = require('i18n-light')\n\n...\n\ni18n.configure({\n  dir: path.join(__dirname, 'dict'),\n  defaultLocale: 'en',\n  fallback: true,\n  cache: true,\n  extension: 'json',\n  refresh: false\n})\n\napp.use(i18n.init())\n\napp.get('/', function(req, res) {\n  i18n.setLocale('en')\n  console.log(i18n.__('common.logo'))          // =\u003e 'i18n-light'\n  console.log(i18n.__('home.logout'))          // =\u003e 'Logout'\n  console.log(i18n.__('home.loggedin', 'Tom')) // =\u003e 'Hello Tom'\n  console.log(i18n.__('home.messages', 2))     // =\u003e '2 messages'\n})\n\napp.get('/it', function(req, res) {\n  i18n.setLocale('it')\n  console.log(i18n.__('common.logo'))          // Will fallback to en =\u003e 'i18n-light'\n  console.log(i18n.__('home.logout'))          // =\u003e 'Esci'\n  console.log(i18n.__('home.loggedin', 'Tom')) // =\u003e 'Ciao Tom'\n  console.log(i18n.__('home.messages', 2))     // =\u003e '2 messaggi'\n})\n\n...\n\nrequire('http').createServer(app).listen(8080)\n```\n\n### Views Example\n\n```html\n...\n\u003cbody\u003e\n  \u003cspan\u003e\u003c%=i18n.__('common.logo')%\u003e\u003c/span\u003e \u003c!-- i18n-light --\u003e\n\u003c/body\u003e\n...\n```\n\n## Options\n| Name | Type | Default | Description |\n|------|------|---------|-------------|\n| `defaultLocale` | `String` | `Required` | The locale which `i18-light` will fallback if a `dictionary path` isn't resolvable in the current dictionary. |\n| `dir` | `String` | N/A | The directory path where the `dictionaries` will reside. |\n| `context` | `Object` | N/A | Instead of using `dir` to instruct `i18n-light` from where to retrieve the dictionaries, you can pass `dictionaries` directly through the `context`. Note: `i18n-light` will only look for this attribute if dir isn't specified. More information below. |\n| `fallback` | `Boolean` | `true` | Indicates whether `i18n-light` should fallback to the `defaultLocale` `dictionary context` if the path is invalid in the `dictionary context` of the current locale. |\n| `refresh` | `Boolean` | `false` | Indicates whether `i18n-light` should retrieve an update of the `dictionary context` (`true`) or keep using what is already cached (`false`). |\n| `cache` | `Boolean` | `true` | Indicates whether `i18n-light` should cache `dictionary context`s (`true`) or not (`false`). |\n| `extension` | `String` | `.js` | The `extension` of the `dictionary` files. |\n| `resolve` | `Function` | `null` | Instead of using `dir` or `context` you can use this function to code your own resolver for your `dictionary` files. Note that `i18n-light` will only use this function if your `i18n-light` instance is not configured using either `context` or `dir`. More info on how to use [here](#using-your-own-resolver)|\n\n## API\n### configure(opts)\nMethod used to configure (initiate) an instance of `i18n-light`. Take a look at the [options section](#options) to understand what options it accepts.\n\n```javascript\n...\ni18n.configure({\n  dir: path.join(__dirname, 'dict'),\n  defaultLocale: 'en',\n  fallback: true\n})\n...\n```\n\n### init()\nMiddleware method. This is the method used to integrate `i18n-light` instance to `Express`. Take a look at the [usage section](#usage) example to see how this can be easily done. This method makes your `i18n-light` instance accessible from:\n\n1. `res.i18n`\n2. `res.locals.i18n` - making your instances accessible from your views.\n\n```javascript\n...\napp.use(i18n.init())\n...\n```\n\n### resetLocale([refresh])\nMethod used to reset the current locale to the default one. It has an optional parameter `refresh` which when its `true` `i18n-light` updates the dictionary context of the default locale.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en'\n  ...\n})\n...\ni18n.setLocale('it')  //default locale is now 'it'\n...\ni18n.resetLocale()  //default locale is now 'en'\n```\n\n### setLocale(locale[, refresh])\nMethod used to change the current locale of your `i18n-light` instance to `locale`. It has an `optional` argument `refresh` which when its `true`, `i18n-light` updates the dictionary context of `locale`.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en'\n  ...\n})\n...\ni18n.setLocale('it')  //default locale is now 'it'\n```\n\n### getLocale()\nMethod used to get the name of the current locale.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en'\n  ...\n})\n...\ni18n.getLocale()  // =\u003e en\n...\ni18n.setLocale('it')\n...\ni18n.getLocale()  // =\u003e it\n```\n\n### isCached(locale)\nMethod used to check whether a `dictionary context` of `locale` is cached or not.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en'\n  ...\n})\n...\ni18n.isCached('en')  // =\u003e true\n...\ni18n.isCached('it')  // =\u003e false\n...\ni18n.setLocale('it')\n...\ni18n.isCached('it')  // =\u003e true\n```\n\n### setDefaultLocale(locale)\nMethod used to change the default locale of your `i18n-light` instance to `locale`.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en'\n  ...\n})\n...\ni18n.getLocale()              // =\u003e en\n...\ni18n.setDefaultLocale('it')   // =\u003e true\n...\ni18n.getLocale('it')          // =\u003e it\n```\n\n### refreshContext([locale])\nMethod used to refresh the `dictionary context` of `locale`.\n\n### clearCache([refresh])\nMethod used to clear the cache of your `i18n-light` instance.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en'\n  ...\n})\n...\ni18n.setLocale('it')    // =\u003e en\n...\ni18n.isCached('en')     // =\u003e true\ni18n.isCached('it')     // =\u003e true\n...\ni18n.clearCache()\n...\ni18n.isCached('en')     // =\u003e false\ni18n.isCached('it')     // =\u003e false\n```\n\nIt has an `optional` argument `refresh` which when its true, `i18n-light` refreshes the `dictionary context` of the current locale.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en'\n  ...\n})\n...\ni18n.setLocale('it')    // =\u003e en\n...\ni18n.isCached('en')     // =\u003e true\ni18n.isCached('it')     // =\u003e true\n...\ni18n.clearCache(true)\n...\ni18n.isCached('en')     // =\u003e false\ni18n.isCached('it')     // =\u003e true\n```\n\n### __(path[,arg1 [,arg2[,..]]])\nMethod used by `i18n-light` to convert `path` to the localized phrase within the current `dictionary context` of the current locale (or default locale if path is invalid and `fallback` === true).\n\nThis method makes use of [sprintf-js](https://www.npmjs.com/package/sprintf-js), enabling you to include placeholders in your `dictionary` phrases (see example).\n\nNote that if `path` is not resolvable `i18n-light` will return the path itself.\n\n#### Dictionary\n```javascript\n{\n  \"home\": {\n    \"login\": \"Login\",\n    \"welcome\": \"Welcome %s\"\n  }\n}\n```\n\n#### Code\n```javascript\n...\ni18n.__('home.login')           // =\u003e 'Login'\ni18n.__('home.welcome', 'Tom')  // =\u003e 'Welcome Tom'\n...\n```\n\n### __n(path[,arg1 [,arg2[,..]]], count)\nMethod used by `i18n-light` to convert `path` to a quantitative localized phrase within the current `dictionary context` of the current locale (or default locale if path is invalid and `fallback` === true).\n\nThis method makes use of [sprintf-js](https://www.npmjs.com/package/sprintf-js), enabling you to include placeholders in your `dictionary` phrases (see example).\n\nNote that if `path` is not resolvable `i18n-light` will return the path itself.\n\nAlso note that the last argument (`count`) is used only by `i18n-light` and not by `sprintf-js`.\n\nIf `count === 0` or is a `String` it will append `.zero` to `path`.\n\nIf `count === 1` it will append `.one` to `path`.\n\nIf `count \u003e 1` it will append `.many` to `path`.\n\n#### Dictionary\n```javascript\n{\n  \"home\": {\n    \"messages\": {\n      \"zero\": \"No messages\",\n      \"one\": \"1 message\",\n      \"many\": \"%s messages\"\n    }\n  }\n}\n```\n\n#### Code\n```javascript\n...\ni18n.__n('home.messages', 0)      // =\u003e 'No messages'\ni18n.__n('home.messages', 1)      // =\u003e '1 Message'\ni18n.__n('home.messages', 3)      // =\u003e 'undefined messages'\ni18n.__n('home.messages', 3, 3)   // =\u003e '3 messages'\n...\n```\n\n## Using your own Resolver\nAs already mentioned in the [options](#options) section, `i18n-light` will only use this functionality if it hasn't been configured with `dir` or `context` options. When a context of a locale is needed, `i18n-light` will call this function with the locale name passed as the parameter. This function should then return a `dictionary context` in the form of a JSON.\n\n```javascript\ni18n.configure({\n  defaultLocale: 'en',\n  resolve: function(locale){\n    $.ajax({\n      type: 'GET',\n      url: 'dict/' + locale + '.js',\n      dataType: 'json',\n      success: function(data) {\n        return data\n      },\n      async: false\n    });\n  }\n  ...\n})\n```\n\n## Browserify\nIntead of using the `dir` option to point to the dictionaries directory, you have the possibility to inject your own `dictionary context`s during the configuration of `i18n-light` instance using `context` option. As already stated, in order for `i18n-light` to use the `context` option, the `dir` option needs to be omitted.\n\nThe following example shows how can this be done using [brfs](https://www.npmjs.com/package/brfs) for `browserify`.\n\n```javascript\nvar i18n = require('i18n-light');\n\ni18n.configure({\n  defaultLocale: document.documentElement.lang,\n  context: { 'en': JSON.parse(require('fs')\n                      .readFileSync('en.js', 'utf-8'))\n            , 'it': JSON.parse(require('fs')\n                      .readFileSync('it.js', 'utf-8'))\n            }\n})\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftabone%2Fi18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftabone%2Fi18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftabone%2Fi18n/lists"}