{"id":42847498,"url":"https://github.com/arendtio/simple-intl","last_synced_at":"2026-01-30T11:59:15.188Z","repository":{"id":57360270,"uuid":"96151522","full_name":"arendtio/simple-intl","owner":"arendtio","description":"This is a simple integration for the powerful format.js","archived":false,"fork":false,"pushed_at":"2017-07-24T20:12:23.000Z","size":35,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-26T07:27:58.887Z","etag":null,"topics":["dictionaries","formatjs","i18n","internationalization","intl","l10n","language","localization","translation"],"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/arendtio.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":"2017-07-03T21:22:27.000Z","updated_at":"2017-07-17T16:58:40.000Z","dependencies_parsed_at":"2022-09-06T22:30:51.187Z","dependency_job_id":null,"html_url":"https://github.com/arendtio/simple-intl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/arendtio/simple-intl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arendtio%2Fsimple-intl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arendtio%2Fsimple-intl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arendtio%2Fsimple-intl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arendtio%2Fsimple-intl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arendtio","download_url":"https://codeload.github.com/arendtio/simple-intl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arendtio%2Fsimple-intl/sbom","scorecard":{"id":206168,"data":{"date":"2025-08-11","repo":{"name":"github.com/arendtio/simple-intl","commit":"fdc0ea0dd3d6dce0dbb80641cdb0f12e072478a4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/15 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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"41 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx","Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-9vvw-cc9w-f27h","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-hr2v-3952-633q","Warn: Project is vulnerable to: GHSA-9q64-mpxx-87fg","Warn: Project is vulnerable to: GHSA-jc84-3g44-wf2q","Warn: Project is vulnerable to: GHSA-qrmc-fj45-qfc2","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-8r6j-v8pm-fqw3","Warn: Project is vulnerable to: MAL-2023-462","Warn: Project is vulnerable to: GHSA-xf7w-r453-m56c","Warn: Project is vulnerable to: GHSA-44pw-h2cw-w3vq","Warn: Project is vulnerable to: GHSA-jp4x-w63m-7wgm","Warn: Project is vulnerable to: GHSA-c429-5p7v-vgjp","Warn: Project is vulnerable to: GHSA-6x33-pw7p-hmpq","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-wrvr-8mpx-r7pp","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-gqgv-6jq5-jjj9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-6g33-f262-xjp4","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-2m39-62fm-q8r3","Warn: Project is vulnerable to: GHSA-mf6x-7mm4-x2g7","Warn: Project is vulnerable to: GHSA-j44m-qm6p-hp7m","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-g7q5-pjjr-gqvp","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T23:49:33.136Z","repository_id":57360270,"created_at":"2025-08-16T23:49:33.136Z","updated_at":"2025-08-16T23:49:33.136Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28912199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T11:55:24.701Z","status":"ssl_error","status_checked_at":"2026-01-30T11:54:13.194Z","response_time":66,"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":["dictionaries","formatjs","i18n","internationalization","intl","l10n","language","localization","translation"],"created_at":"2026-01-30T11:59:14.182Z","updated_at":"2026-01-30T11:59:15.179Z","avatar_url":"https://github.com/arendtio.png","language":"JavaScript","readme":"# Simple-Intl\n\nSimple i18n library based on the powerful\n[formatjs.io](https://formatjs.io).\n\nInternationalization (i18n) is hard. In the beginning, we often\nthink 'Hey, let's take all our texts into a dictionary and use\ndifferent dictionaries for different languages'. After a while, we\nnotice that that's not enough, as values with different quantities\nrequire different translations. So we solve that problem for the\nfirst languages we support and later we find out that our solution\nis not good enough for other languages. And so on...\n\nLuckily, there are tools like formatjs.io. It is a mature project\nwhich offers you a solution based on the standardized Internationalization API\n[ECMA-402](http://www.ecma-international.org/ecma-402/1.0/).\n\nFormatjs.io offers [integrations](https://formatjs.io/integrations/)\nfor some popular frameworks and otherwise the core libraries, but as\nthe usage of the core-libs has its own complexity, this project was\ncreated to wrap the power of formatjs.io into a simple function.\n\n\n# Usage\n\nThe hardest part is the installation and integration of your\nproject. When everything is set up and running displaying a\ntranslated text is just a matter of calling a function like:\n\n```\ni18n(\"G_HELLO_WORLD_KEY\");\n```\n\nMore complex examples can be found in the `demo.html`.\n\n# Demo\n\nTo see it in action, you can simply clone this repository, download\nthe dependencies and serve it with a local web server:\n\n```bash\n# download the project\ngit clone https://github.com/arendtio/simple-intl.git\n\ncd simple-intl\n\n# download the dependencies\nnpm install\n\n# serve the current directory on port :8080\nnpm start\n\n# open http://localhost:8080/demo.html in a browser\n```\n\n# Installation\n\nIn its current state simple-intl is designed for the browser. As\ntherefore, installation means 'intergration to your project', it is\nthe best to start with the demo and take what you need from there.\n\nTo download everything you need, you can start with npm:\n```\nnpm install simple-intl\n```\n\nNow we can start to integrate it into your project. So before we can\nuse any translations we need to create them. Just for the sake of\nthis let's create a file for English and one for German:\n\nEnglish (i18n/en.json):\n```\n{\n\t\"G_HELLO_WORLD_TXT\": \"Hello World.\"\n}\n```\n\nGerman (i18n/de.json):\n```\n{\n\t\"G_HELLO_WORLD_TXT\": \"Hallo Welt.\"\n}\n```\n\nThe name of the files must be of the pattern `[locale].json`, while\nthe [locale] must be part of the list of `availableLanguages`.\n\nTo be able to use simple-intl there are some dependencies which must\nbe loaded before it can be used. The first is a polyfill for the\nInternationalization API which is not yet implemented in all\n[browsers](https://cdn.polyfill.io/v2/docs/features/#Intl):\n\n```html\n\u003cscript src=\"https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en,Intl.~locale.de\"\u003e\u003c/script\u003e\n```\n\nNext we have to load two of the core libraries of formatjs.io:\n\n```html\n\u003cscript src=\"node_modules/intl-messageformat/dist/intl-messageformat.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"node_modules/intl-relativeformat/dist/intl-relativeformat.min.js\"\u003e\u003c/script\u003e\n```\n\nAn finally we have to load simple-intl itself:\n\n```html\n\u003cscript src=\"node_modules/simple-intl/dist/simple-intl.min.js\"\u003e\u003c/script\u003e\n```\n\nNow we are ready to use it. To do that, there is a global function\ncalled `simpleintl` which takes a few arguments and returns an\ninstance which can be used to replace translation keys with the\ncorresponding translations.\n\nTo be able to detect the best language\nfor the user (from the browser settings), we have to tell simple-intl\nfor which **languages** we have translations for our page/app.\n\nFurthermore, simple-intl has to fetch some files depending on the\nselected language to help it find those files, we can set a few\n**options**.\n\nLast but not least, simple-intl will take a moment to\ninitialize the instance and takes a **callback** function which is being\ncalled when the returned function is ready to be used:\n\n```javascript\nvar available = [\"en\", \"de\"];\n\nvar options = {\n\tlocaleDataPath: \"node_modules/intl-messageformat/dist/locale-data\",\n\trelativeLocaleDataPath: \"node_modules/intl-relativeformat/dist/locale-data\",\n\tmessagesPath: \"i18n\",\n}\n\n// i18n should be used by convention\nvar i18n = simpleintl(available, options, function() {\n\tconsole.log(\"i18n is now ready to be used\");\n\talert(i18n('G_HELLO_WORLD_TXT'));\n});\n```\n\nWhen no language from the browser settings matches the available\nlanguages simple-intl takes the first available language as fallback.\n\nFor educational reasons, we left all dependencies in their\ndirectories, but actually, simple-intl assumes to find the files in\nmore appropriate places by default.\n\n# Documentation\n\nConceptionally simple-intl consists of two parts:\n\n1. the static methods to create instances\n2. the instance methods\n\nThe static methods have no state. Every instance has its own cache\nand dictionaries (one per language). New instances can not be used\nuntil they have loaded a language. Loading languages, however, is an\nexpensive process as new file need to be downloaded.\n\nTo keep things simple and performant it is advised to have one global\ninstance called `i18n` and use additional instances only when required.\n\nEvery instance has its own options. By default every instance uses\nthe following options:\n\n```json\n{\n\t\"localeDataPath\": \"js/intl-messageformat/locale-data\",\n\t\"relativeLocaleDataPath\": \"js/intl-relativeformat/locale-data\",\n\t\"messagesPath\": \"i18n\"\n}\n```\n\n## Static Methods (simpleintl)\n\n- `simpleintl(availableLanguages, [ options,] readyCallback)`: The common\nmethod to create a new instance. It creates a new instance, patches\nto options, detects the preferred language, loads that language and\ncalls the callback when it is ready. It returns the new instance.\n\n- `simpleintl.createInstance([options])`: Less eager method to create a\nnew instance. It just creates a new instance and patches the\noptions. Before that new instance can be used the language must be\nloaded manually (i18n.loadLanguage). It returns the new instance.\n\n- `simpleintl.detectLanguage(availableLocales, fallbackLocale)`:\nTries to find the best match between availableLocales and browser\nsettings. `availableLocales` has to be an Array with locales\n(Strings in the form of 'en' or 'en-US'). `fallbackLocale` must be\nthe locale the function should return if no availableLocale matches\nthe user's preferences. Before it looks at the\nbrowser settings it takes a look at the localStorage key\n`i18n-selected-locale`. So settings that key makes it possible to\nlet the user select a language without having to change the browser\nsettings. The function returns the first matching locale. If it does\nnot match any availableLocale, it returns the fallbackLocale.\n\n- `simpleintl.browserLanguages()`: Returns an Array with the\npreferred languages according to the browser settings in descending\norder. The localStorage key mentioned in `detectLanguage` is\nincluded here too (if it exists).\n\n## Instance Methods (i18n)\n\nThe instance methods can be split into 2 groups:\n\n1. Translation methods\n2. Utility Methods\n\n### Translation Methods\n\nThe translation methods are the actual methods which are the\nplaceholders of the strings that should be displayed.\n\n- `i18n(key [, args, opts])`: The `key` (string) is the key of the\ndictionary to find the related translation. `args` is an object\nwhich properties are the names of the dynamic values within the\ntranslation. `opts` are special options related to the `args`. More\ninformation about the formats can be found\n[here](https://formatjs.io/guides/message-syntax/) and\n[here](https://github.com/yahoo/intl-messageformat).\n \n- `i18n.number(value [, opts])`: Formats a number (value) based on the\nactive language and `opts`.\n\n- `i18n.date(value [, opts])`: Formats a date (value) based on the active\nlanguage and the `opts`.\n\n- `i18n.relative(value [, opts])`: Formats a date into a relative time\nstring. More information can be found\n[here](https://github.com/yahoo/intl-relativeformat).\n\nFurthermore, some examples can be found in the `demo.html`.\n\n### Utility Methods\n\nIn most cases, it should be enough to create an instance with\n`simpleintl()` and use it afterward. In other cases the following\nmethods might be useful:\n\n- `i18n.patchOptions(opts)`: `opts` should be an object which\nproperties are the same as those of the default options object.\nOnly properties which are present in the `opts` object will be\nchanged.\n\n- `i18n.loadLanguage(locale, callback)`: Sets the `locale` as\n`activeLanuage` and downloads the required language files.\n`callback` is called as soon as all files have been fetched and\nloaded.\n\n- `i18n.setLanguage(locale, data)`: Sets the `locale` as\n`activeLanuage` and data as the dictionay for the provided locale.\nThis method is an alternative to `i18n.loadLanguage` and can be used\nwhen the dictionary data should not be loaded from a json file (e.g.\nin a node.js app).\n\n- `i18n.activeLanguage([forceShort])`: Returns the currently\nactive/loaded Language. If `forceShort` is set it only returns the\nfirst 2 characters of the active Locale.\n\n- `i18n.detectLanguage(availableLocales, fallbackLocale)`: Just the\n  same as `simpleintl.detectLanguage()`\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farendtio%2Fsimple-intl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farendtio%2Fsimple-intl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farendtio%2Fsimple-intl/lists"}