{"id":28238468,"url":"https://github.com/edificeio/sijil.js","last_synced_at":"2026-04-25T23:36:31.326Z","repository":{"id":57359496,"uuid":"72781167","full_name":"edificeio/sijil.js","owner":"edificeio","description":"A simple and elegant i18n library","archived":false,"fork":false,"pushed_at":"2023-10-10T21:20:54.000Z","size":978,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-10-02T01:55:13.860Z","etag":null,"topics":["angular","i18n","internationalization","language","translation"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edificeio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2016-11-03T19:50:35.000Z","updated_at":"2019-11-20T10:07:45.000Z","dependencies_parsed_at":"2024-02-14T12:52:43.958Z","dependency_job_id":null,"html_url":"https://github.com/edificeio/sijil.js","commit_stats":null,"previous_names":["web-education/sijil.js","edificeio/sijil.js"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/edificeio/sijil.js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edificeio%2Fsijil.js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edificeio%2Fsijil.js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edificeio%2Fsijil.js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edificeio%2Fsijil.js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edificeio","download_url":"https://codeload.github.com/edificeio/sijil.js/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edificeio%2Fsijil.js/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32280979,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"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":["angular","i18n","internationalization","language","translation"],"created_at":"2025-05-19T01:12:58.101Z","updated_at":"2026-04-25T23:36:31.312Z","avatar_url":"https://github.com/edificeio.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sijil\n#### *[SI]mple [J]son [I]nternationalization [L]ibrary*\n\n[![Build Status](https://travis-ci.org/web-education/sijil.js.svg)](https://travis-ci.org/web-education/sijil.js)\n\n## Introduction\n\nSijil is a simple but powerful i18n library.\nIt can be used in conjunction with angular2, or as an old fashioned \u0026lt;script\u0026gt; inclusion.\n\nSijil is (very) basically a javascript object with one entry by language loaded,\nwhich contains all the translations available as key/values.\n\nLike this :\n```json\n{\n    \"en\": { \"hello\": \"Hi\", \"bye\": \"Bye\" },\n    \"fr\": { \"hello\": \"Salut !\", \"bye\": \"Au revoir\" }\n}\n```\n\nBut the interesting part is that we can use parameters and combine them with the final output.\n\n`Here is {{ name ? name : Nobody }} and {{ male ? his : her }} {{ 1 \u003c bunnyCount ? $bunnyCount bunnies : bunny }}.`\n\nThe library is also completely customizable, from the Loader to the Parser.\n\n*( [Demo](https://opendigitaleducation.github.io/sijil.js/docs/) )*\n\n## Installation\n\n### Using npm\n\n`npm install opendigitaleducation/sijil.js --save-dev`\n\n### Or bower\n\n\u003ebower cli\n\n`bower install opendigitaleducation/sijil.js`\n\n\u003ebower.json\n\n```json\n\"dependencies\": {\n    \"sijil\": \"opendigitaleducation/sijil.js#master\"\n}\n```\n\nThen : `bower install`\n\n### Or build it yourself\n\n- clone this repo\n- `npm install`\n- `npm start`\n\nDistribution files will be located inside the `dist` folder.\n\n## Use it\n\n### *With angular2*\n\nUse the es6 files (`index.js` as the entry point) and d.ts definitions, or the umd.bundle (`dist/bundles/sijil.module.umd.js`).\n\nFor example, with SystemJs loader, inside the `systemjs.config.js` file :\n\n```javascript\n System.config({\n     // ... //\n     map: {\n         // ... //\n         'sijil': 'npm:sijil/dist/bundles/sijil.module.umd.js'\n         // ... //\n     }\n     // ... //\n })\n```\n\n#### Import the module\n\n```typescript\nimport { SijilModule } from 'sijil'\n\n@NgModule({\n    imports: [\n        /* ... */\n        SijilModule.forRoot(), // In the root module\n        // OR\n        SijilModule.forChild() // For lazily loaded modules\n        /* ... */\n     ]\n})\n```\n\n#### Inside a component\n\n- Inject the main service :\n\n```typescript\nimport { BundlesService } from 'sijil'\n\n/* ... */\n\nconstructor(/*...*/, private bundlesService: BundlesService, /*...*/){}\n```\n\n- Load a bundle :\n\n```typescript\nthis.bundlesService.loadBundle('/path/to/the/language/file.json', 'en')\n    .then(/* The bundle is loaded. */)\n    .catch(...)\n```\n\nThe default loader will perform an http request at the specified path to retrieve a json file.\nThe contents will be added to the current language bundle (or the specified language as the 2nd argument).\n\n- Inside a template\n\n```html\n    \u003c!-- USING THE S5L HTML TAG --\u003e\n\n    \u003cs5l\u003ehello\u003c/s5l\u003e\n    \u003c!-- Force a language --\u003e\n    \u003cs5l s5l-lang='en'\u003ehello\u003c/s5l\u003e\n    \u003c!-- With parameters --\u003e\n    \u003cs5l [s5l-params]=\"{ itemNumber: 3 }\"\u003ecount.key\u003c/s5l\u003e\n    \u003c!-- count.key being mapped to something like \"There {{ itemNumber \u003e 1 ? are $itemNumber items : is one item }} in the room\" --\u003e\n\n    \u003c!-- USING THE TRANSLATE PIPE --\u003e\n\n    {{ 'hello' | translate }}\n    \u003c!-- As an attribute --\u003e\n    \u003cinput attr.placeholder=\"{{ 'enter.your.name' | translate }}\" /\u003e\n    \u003c!-- Force a language --\u003e\n    {{ 'hello' | translate:{}:'fr' }}\n    \u003c!-- With parameters --\u003e\n    {{ 'count.key' | translate:{itemNumber: 3} }}\n```\n\n#### forRoot\n\n```typescript\nstatic forRoot(require?: Type\u003cRequireService\u003e, parser?: Type\u003cParser\u003e, options?: SijilOpts): ModuleWithProviders\n```\n\nThe forRoot method can be used to override the default services :\n\n```typescript\nclass DummyRequire implements RequireService {\n    load(){ return new Promise(res =\u003e { res({ 'key': 'value'}) }) }\n}\n\nclass DummyParser implements Parser {\n    compile(text){ return text }\n}\n\nlet dummyOpts = {  defaultLanguage: 'en' }\n\n@NgModule({\n    imports: [\n        /* ... */\n        SijilModule.forRoot(DummyRequire, DummyParser, dummyOpts)\n        /* ... */\n     ]\n})\n```\n\n### *Without angular2*\n\nInclude via a `\u003cscript src=\"[your.sijil.path]/dist/bundles/sijil.js\u003e\u003c/script\u003e` tag.\n\nThen use the global `Sijil` object as needed.\n\n```html\n \u003cscript src=\"../dist/bundles/sijil.js\"\u003e\u003c/script\u003e\n```\n\n```javascript\n// Loads /docs/language.json file.\nSijil.loadBundle('/docs/' + Sijil.defaultLanguage + '.json').then(function(){\n    // Adds the 'test' key to the bundle.\n    Sijil.addToBundle({ 'test': '[OK] Sijil is now loaded.' })\n    // Logs it.\n    console.log(Sijil.translate('test'))\n})\n```\n\n#### factory :\n\nThe factory method can be used to override the default services :\n\n```typescript\n// Internal definition of the factory function :\nSijil['factory'] = (require: RequireService, parser: Parser, opts: SijilOpts) =\u003e {\n    return new BundlesService(require || new XHRRequire(), parser || new FragmentsParser(), opts || defaultSijilOpts)\n}\n```\n\n```javascript\n// Usage in your code :\nlet sijilInstance = Sijil.factory({\n        // Dummy loader\n        load: () =\u003e { return new Promise(res =\u003e { res({ 'key': 'value'}) }) },\n    }, {\n        // Dummy parser\n        compile: (text) =\u003e text\n    }, {\n        // Dummy options\n        defaultLanguage: 'en'\n    })\nsijilInstance.loadBundle().then(() =\u003e { console.log(sijilInstance.translate('key')) })\n// \u003c-- Outputs 'value'\n```\n\n## Methods\n\n#### loadBundle\n*or loadBundles for multiple bundles*\n\nLoads a bundle and associates it with a language.\nIf the target language already contains key/values, then we mixin the new bundle and the existing one.\n\n```typescript\nloadBundle(where, lang?: string) : Promise\u003cvoid\u003e\n```\n\n#### translate\n*the method called by the translate pipe and the s5l tag*\n\nTranslates a single key into a target language, using the parameters provided if needed.\n\n```typescript\ntranslate(key: string, parameters?: Object | any[], lang?: string) : string\n```\n\n#### unloadBundle\n\nRemoves a bundle from the bundles list.\n\n```typescript\nunloadBundle(lang: string) : void\n```\n\n#### getLoadedLanguages\n\nReturns a list of all loaded languages.\n\n```typescript\ngetLoadedLanguages() : string[]\n```\n\n## Architecture\n\n### Require Service\n\nA RequireService is used to fetch bundles. It contains a single `load: (from: any) =\u003e Promise\u003cObject\u003e` method,\nwhich loads the bundle according to its argument value.\n\nThe default RequireService provided (HttpRequireService for angular2 users, XhrRequireService otherwise) fetches the bundles from an url and parses json from the reponse.\n\n### Parser Service\n\nA ParserService computes any logic provided in the translations.\n\n- Input : 'raw' translation + parameters (Object or Array)\n- Output : 'compiled' translation\n\nThe default provider instanciates a FragmentsParserService, which accepts the syntax described below.\n\n#### FragmentsParserService\n\nLogic is contained inside mustache blocks : `{{ logic block }}`\n\nThere are two variants :\n\n##### A single parameter key or index\n\n*A key when the parameters are contained inside an object or an index when the parameters are contained inside an array*\n\nExamples:\n\n`{{ key }}` + `{ \"key\" : \"my key\" }` = `my key`\n\n`{{ 1 }}` + `[1, 2]` = `2`\n\n##### A ternary-like condition\n\n`{{ condition ? trueValue : falseValue }}`\n\n`{{ leftClause operator rightClause ? trueValue : falseValue }}`\n\nWhere condition may be either a single parameter key/index, or 2 clauses with the following operators : `==, \u003e, =\u003e, \u003c=, \u003c`\n\nExamples:\n\n*the $ sign is used in ambiguous cases to refer to the parameter*\n\n`{{ count \u003e 1 ? $count cats : 1 cat }}` + `{\"count\": 10}` = `10 cats`\n\n`{{ 1 \u003c count ? $count cats : 1 cat }}` + `{\"count\": 1}` = `1 cat`\n\n##### Parameters array or parameter objects ?\n\nThe syntax is the same, but with indexes instead of names :\n\n`{{ $0 \u003e 1 ? $0 cats : 1 cat }}` + `[10]` = `10 cats`\n\n`{{ 1 \u003c $0 ? $0 cats : 1 cat named $1 }}` + `[1, 'Albert']` = `1 cat named Albert`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedificeio%2Fsijil.js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedificeio%2Fsijil.js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedificeio%2Fsijil.js/lists"}