{"id":19777468,"url":"https://github.com/ilib-js/ilib-loctool-json","last_synced_at":"2025-04-30T19:32:33.210Z","repository":{"id":41847690,"uuid":"172766421","full_name":"iLib-js/ilib-loctool-json","owner":"iLib-js","description":"Ilib loctool plugin to parse and localize json files","archived":true,"fork":false,"pushed_at":"2024-11-12T13:05:50.000Z","size":129,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-20T14:45:27.487Z","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":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iLib-js.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-26T18:26:52.000Z","updated_at":"2024-11-21T22:03:52.000Z","dependencies_parsed_at":"2023-02-09T12:31:00.715Z","dependency_job_id":"57737103-3e89-4b8c-9f20-2fae5c55d3d3","html_url":"https://github.com/iLib-js/ilib-loctool-json","commit_stats":{"total_commits":72,"total_committers":4,"mean_commits":18.0,"dds":0.125,"last_synced_commit":"57203736ff22e6c945f3325b7ed92d7c63f902df"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-loctool-json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-loctool-json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-loctool-json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-loctool-json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iLib-js","download_url":"https://codeload.github.com/iLib-js/ilib-loctool-json/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251769510,"owners_count":21640917,"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","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":"2024-11-12T05:25:09.117Z","updated_at":"2025-04-30T19:32:33.193Z","avatar_url":"https://github.com/iLib-js.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003e :warning: **Deprecation Notice** :warning:\n\u003e This repository has been deprecated. Please use the corresponding package from the [iLib-js monorepo](https://github.com/iLib-js/ilib-mono) instead.\n\n# ilib-loctool-json\n\nIlib loctool plugin to parse and localize json files.\n\nThis plugin can parse and localize json files by either\nunderstanding the schema via a jsonschema v7 file, or by\ndefaulting to a list of key/value pairs.\n\n## Style of JSON\n\nBy default, this plugin assumes that the json file\nconforms to the [Json5 spec](http://json5.org). Earlier\nforms of json are subsets\nof Json5, so Json5 is the most flexible standard to\nprocess.\n\nThis means you can put comments in the json\nfile itself or have trailing commas, etc.\nSome of these comments are\nprocessed along with string values to add optional\ntranslator comments to the strings. The localized\noutput files will conform to older versions of json\n\n## Methods of Localizing\n\nJson files are localized in one of the following\nmethods:\n\n1. copy. Make a copy of the entire source file\nand replace values of certain properties in the\ncopy with translations. The copy can be sent to\nany output desired directory using a template.\nCopy is the default method with which\nlocalized json files are handled.\n1. sparse. Make a copy of the source file where only\nthe localized properties appear. The copy has the same\nstructure as the original json file, but only properties\nwhere the value is localized appear in the output.\n\nThe first method, localizing the entire file, has the\nadvantage that you don't need to change your code in\norder to read the translated file. You just need to pick\nthe right file for the current locale.\n\nThe second method is similar to the\nfirst method above, except that it can save space\nbecause all of the non-localizable data in the original\njson file is not duplicated.\nIn this case, you would need to load in the English file\nfirst, then mix-in the localized file to override all\nthe localizable strings in order to create the full\ndata with localized data embedded in it.\n\n## Key/Value Pairs\n\nIn the absence of any schema information, a default\nschema will be applied. The\nplugin will assume that the json file is a simple object\nwhere the property names are the keys and the property\nvalues are the strings to translate.\n\nExample:\n\n```json\n{\n    \"unique id 1\": \"first string to translate\",\n    \"unique id 2\": \"second string to translate\",\n    etc.\n}\n```\n\nEssentially, this means that we assume that the file has\nthe following json schema:\n\n```json\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"strings-schema\",\n    \"type\": \"object\",\n    \"description\": \"A flat object of properties with localizable values\",\n    \"additionalProperties\": {\n        \"type\": \"string\",\n        \"localizable\": true\n    }\n}\n```\n\n## Configuring the Plugin\n\nThe plugin will look for the `json` property within the `settings`\nof your `project.json` file. The following settings are\nused within the json property:\n\n- schemas: a string naming a directory full of json schema files, or\n  an array of strings naming some json schema files or directories to\n  load. If the json file\n  does not fit any of the schema (ie. it does not validate according to\n  any one of the schema), then that file will be skipped and not localized.\n- mappings: a mapping between file matchers and an object that gives\n  info used to localize the files that match it. This allows different\n  json files within the project to be processed with different schema.\n  The matchers are\n  a [micromatch-style string](https://www.npmjs.com/package/micromatch),\n  similar to the the `includes` and `excludes` section of a\n  `project.json` file. The value of that mapping is an object that\n  can contain the following properties:\n    - schema: schema to use with that matcher. The schema is\n      specified using the `$id` of one of the schemas loaded in the\n      `schemas` property above. The default schema is \"strings-schema\"\n      which is given in the previous section.\n    - method: one of \"copy\" or \"sparse\"\n        - copy: make a copy of the source file and localize the\n          string contents. (This is the default method if not specified\n          explicitly.)\n        - sparse: make a copy of the source file but only\n          include localized strings\n    - template: a path template to use to generate the path to\n      the translated\n      output files. The template replaces strings in square brackets\n      with special values, and keeps any characters intact that are\n      not in square brackets. The default template, if not specified is\n      \"resources/[localeDir]/[filename]\". The plugin recognizes\n      and replaces the following strings in template strings:\n        - [dir] the original directory where the matched source file\n          came from. This is given as a directory that is relative\n          to the root of the project. eg. \"foo/bar/strings.json\" -\u003e \"foo/bar\"\n        - [filename] the file name of the matching file.\n          eg. \"foo/bar/strings.json\" -\u003e \"strings.json\"\n        - [basename] the basename of the matching file without any extension\n          eg. \"foo/bar/strings.json\" -\u003e \"strings\"\n        - [extension] the extension part of the file name of the source file.\n          etc. \"foo/bar/strings.json\" -\u003e \"json\"\n        - [locale] the full BCP-47 locale specification for the target locale\n          eg. \"zh-Hans-CN\" -\u003e \"zh-Hans-CN\"\n        - [language] the language portion of the full locale\n          eg. \"zh-Hans-CN\" -\u003e \"zh\"\n        - [script] the script portion of the full locale\n          eg. \"zh-Hans-CN\" -\u003e \"Hans\"\n        - [region] the region portion of the full locale\n          eg. \"zh-Hans-CN\" -\u003e \"CN\"\n        - [localeDir] the full locale where each portion of the locale\n          is a directory in this order: [langage], [script], [region].\n          eg, \"zh-Hans-CN\" -\u003e \"zh/Hans/CN\", but \"en\" -\u003e \"en\".\n        - [localeUnder] the full BCP-47 locale specification, but using\n          underscores to separate the locale parts instead of dashes.\n          eg. \"zh-Hans-CN\" -\u003e \"zh_Hans_CN\"\n    - localeMap: an output locale map that maps the locale used in the\n      translations to a different locale for use in the file name template.\n      For example, an app may wish to use the locale specifier \"zh-CN\"\n      instead of the full \"zh-Hans-CN\" for some output files, but not\n      all of them. In this case, a locale map for this template mapping\n      is how this can be achieved. Any locale not listed in the mapping\n      will be used as-is. The overall [shared] locale map is also applied\n      if there is no locale map in the template mapping for a particular\n      locale.\n\nExample configuration:\n\n```json\n{\n    \"settings\": {\n        \"json\": {\n            \"schemas\": \"./json/schemas\",\n            \"mappings\": {\n                \"**/appinfo.json\": {\n                    \"schema\": \"http://www.lge.com/json/appinfo\",\n                    \"method\": \"sparse\",\n                    \"template\": \"resources/[localeDir]/appinfo.json\"\n                },\n                \"src/**/strings.json\": {\n                    \"schema\": \"http://www.lge.com/json/strings\",\n                    \"method\": \"copy\",\n                    \"template\": \"[dir]/strings.[locale].json\",\n                    \"localeMap\": {\n                        \"zh-Hans-CN\": \"zh-CN\"\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\nIn the above example, any file named `appinfo.json` will be parsed with the\n`http://www.lge.com/json/appinfo` schema. Because the method is `sparse`,\nonly the parts of the json file that have translated strings in them will\nappear in the output. The output file name is sent to the `resources` directory.\n\nIn the second part of the example, any `strings.json` file that appears in\nthe `src` directory will be parsed with the schema `http://www.lge.com/json/strings`\nand a full copy of the file, including the parts that were not localized,\nwill be sent to the same directory as the source file. However, the\nlocalized file name will also contain the name of the locale to distinguish\nit from the source file.\n\nIf the name of the localized file that the template produces is the same as\nthe source file name, this plugin will throw an exception, the file will not\nbe localized, and the loctool will continue on to the next file.\n\n\n## Extensions to JSON Schema\n\nIn regular JSON Schemas, there is no built-in way to indicate that any value\nis localizable. However, the [JSON Schema spec](https://json-schema.org/specification.html)\nallows for creating extensions\nto the keywords of your json schema and specifies that implementation must\nignore any keywords that it does not recognize.\n\n### The `localizable` Keyword\n\nThis plugin recognizes the new `localizable` keyword as an extension. The\n`localizable` keyword specifies that the value of a property should be\nlocalized by the methods provided above. By default, values are not\nlocalizable unless explicitly specified using the `localizable` keyword.\n\nThe `localizable` keyword is ignored for null or undefined values. For\nthe primitive types string, integer, number, or boolean values, the value\nis directly localizable. Each property will result in a translation unit\nthat the translators may localize.\n\nWhen the `localizable` keyword is given for arrays,\nevery item in the array is localizable and must be of a primitive type\n(string, integer, number, or boolean). If any array entries are not of\na primitive type, an exception will be thrown and the localization will\nbe halted.\n\nWhen the `localizable` keyword\nis given for an object type, that object encodes a plural string. The\nsubproperties allowed in that object are those defined in the [Unicode\nplural rules](http://cldr.unicode.org/index/cldr-spec/plural-rules):\n\n- zero\n- one\n- two\n- few\n- many\n- other\n\nThe \"one\" and the \"other\" property are required for source files in English.\nOther languages will have different combinations of plural categories.\n\nExample json schema file:\n\n```json\n{\n    \"$id\": \"\",\n    \"title\": \"an location data\",\n    \"properties\": {\n        \"name\": {\n            \"type\": \"string\",\n            \"description\": \"the name of this address, like 'work' or 'home'. This string is not localized\",\n            \"$comment\": \"note that this is not localizable\"\n        },\n        \"country\": {\n            \"type\": \"string\",\n            \"localizable\": true,\n            \"description\": \"the name of the country localized the the current language\"\n        },\n        \"latitude\": {\n            \"type\": \"number\",\n            \"localizable\": true,\n            \"description\": \"an example of a localizable number\"\n        },\n        \"places\": {\n            \"type\": \"array\",\n            \"localizable\": true,\n            \"items\": {\n                \"type\": \"string\"\n            }\n        },\n        \"plural\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n                \"type\": \"object\",\n                \"localizable\": true,\n                \"required\": [\n                    \"one\",\n                    \"other\"\n                ],\n                \"properties\": {\n                    \"zero\":  {\"type\": \"string\"},\n                    \"one\":   {\"type\": \"string\"},\n                    \"two\":   {\"type\": \"string\"},\n                    \"few\":   {\"type\": \"string\"},\n                    \"many\":  {\"type\": \"string\"},\n                    \"other\": {\"type\": \"string\"}\n                },\n                \"additionalProperties\": false\n            }\n        }\n    }\n}\n```\n\nThe `localizable` keyword is also ignored for `const` value types, as the\nvalue is supposed to remain constant.\n\nFor strings that have an `enum` keyword, each of the values in the `enum` will\nnot be translated as well, as the code that reads this json file is explicitly\nexpecting one of the given fixed values.\n\n## JSON File Generation\n\nWhen you create a new, empty JsonFile instance that is not backed\nby a json file on disk, this plugin can generate the json file\ntext automatically. This allows this plugin to be used as a resource\nfile type for other plugins.\n\n```javascript\n    // path does not have to exist\n    var jsonFile = jsonFileType.newFile(undefined, {locale: \"fr-FR\"});\n\n    // the string, plural and array resource added in this example\n    // already have translations in them to fr-FR\n    jsonFile.addResource(stringResource);\n    jsonFile.addResource(pluralResource);\n    jsonFile.addResource(arrayResource);\n\n    // first param is the translation set from the xliff files\n    // and can be undefined for generated json files because\n    // the resources already have the translations in them\n    var text = jsonFile.getLocalizedText(undefined, \"fr-FR\");\n```\n\n### Generated File Name\n\nIf the `newFile` method is called without a path name, as in the above example,\nthe default mapping will apply, and the output file will follow the default\nmapping's template. If a path name is given, but does not match any mapping,\nit will also use the default mapping. Otherwise, it will use the matched mapping\nto find the output file name.\n\n### Generation of Each Resource Type\n\nThe generation of resources into json has a hard-coded schema for now.\n(This may change in the future.) The hard-coded format is one that\nworks with ilib's ResBundle class so that the output json can be\nloaded as string resources.\n\nFor strings, they are output as simple key/value pairs:\n\n```json\n{\n    \"key\": \"value\"\n}\n```\n\nFor arrays, they are output as json arrays:\n\n```json\n{\n    \"key\": [\n        \"value at index 0\",\n        \"value at index 1\",\n        etc\n        \"value at index N\"\n    ]\n}\n```\n\nFor plurals, they are output as ilib plural strings:\n\n```json\n{\n    \"key\": \"one#'one' category string|few#'few' category string|#'other' category string\"\n}\n```\n\n## Not a Validator\n\nPlease note that this plugin is *not* a json schema validator, though it\nworks in similar ways. If the json being parsed does not conform to\nthe given schema, no errors or exceptions will be thrown, but it will\nprint some warnings to the output. The strings will merely not be\nextracted/localized as expected.\n\n## License\n\nThis plugin is license under Apache2. See the [LICENSE](./LICENSE)\nfile for more details.\n\n## Release Notes\n\n### v1.5.4\n\n- fixed a bug where array entries without any localizable values in\n  them were being coming out as `null` in the localized json files.\n- updated dependencies\n\n### v1.5.3\n\n- update dependencies\n- convert all unit tests from nodeunit to jest\n\n### v1.5.2\n\n- fixed a bug where the \"anyOf\", \"allOf\", \"oneOf\", and \"not\" keywords\n  in json schemas were not handled properly (or at all!) causing\n  the plugin to miss strings that should be localized\n- update dependencies\n\n### v1.5.1\n\n- update dependencies\n\n### v1.5.0\n\n- added support for locale maps when generating output path names\n\n### v1.4.0\n\n- added the ability to read json files as translated resource files\n    - if the mappings include a template and the path name matches, it\n      will use the locale gleaned from the path name when extracting\n      resources\n\n### v1.3.0\n\n- added the ability to use this plugin as the output resource file format for other\n  plugins\n    - added addResource() to the JsonFile\n    - changed write so that if there is no existing json, it will generate\n      a new json file using hard-coded output templates\n\n### v1.2.5\n\n- Use the logger provided by the loctool instead of trying to log things on our own\n- Use the formatPath and getLocaleFromPath functions provided by the loctool instead\n  of our own\n\n### v1.2.4\n\n- normalize the path before matching against the mappings so that the matching\n  works better\n\n### v1.2.3\n- fix issue of the parser that resulted in skipping objects with\n  single boolean field which equals `false`\n\n### v1.2.2\n\n- Fix a bug where the pseudo locales were not initialized properly. This fix gets\n  the right set of locales from the project settings to see if any of them are pseudo locales.\n\n### v1.2.1\n\n- Fixed bug where it was not generating pseudo localized text properly for missing\n  translations when pseudo is turned on\n\n### v1.2.0\n\n- add support for $refs in array schema definitions\n\n### v1.1.1\n\n- few README.md files (this file!)\n\n### v1.1.0\n\n- extended array support:\n    1. corrected handling of primitive types. Values are casted to their initial type upon translation\n    2. added support for array of objects\n- fixed a bug of a copy method that results in json parts, that are not defined in the schema,\nto be removed from localized files\n\n### v1.0.1\n\n- fixed a bug where plural strings resources were not extracted to the new\n  strings file properly\n\n### v1.0.0\n\n- initial version\n- support json schema and also default schema (key/value pairs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filib-js%2Filib-loctool-json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filib-js%2Filib-loctool-json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filib-js%2Filib-loctool-json/lists"}