{"id":19777492,"url":"https://github.com/ilib-js/ilib-lint","last_synced_at":"2025-04-30T19:32:33.318Z","repository":{"id":64873977,"uuid":"543417997","full_name":"iLib-js/ilib-lint","owner":"iLib-js","description":"A static analysis linter for many types of source files that looks for i18n problems","archived":true,"fork":false,"pushed_at":"2024-11-08T16:50:52.000Z","size":1821,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-12-11T09:06:52.797Z","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":"2022-09-30T03:41:29.000Z","updated_at":"2024-11-21T22:03:17.000Z","dependencies_parsed_at":"2023-12-12T12:29:48.602Z","dependency_job_id":"33a3a345-9d6a-4900-874d-68921e6c0da4","html_url":"https://github.com/iLib-js/ilib-lint","commit_stats":{"total_commits":97,"total_committers":3,"mean_commits":"32.333333333333336","dds":0.07216494845360821,"last_synced_commit":"826635c977af0b93d8391cf91e171755fb654c5b"},"previous_names":["ilib-js/ilib-lint","ilib-js/i18nlint"],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-lint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-lint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-lint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iLib-js%2Filib-lint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iLib-js","download_url":"https://codeload.github.com/iLib-js/ilib-lint/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251769507,"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:16.373Z","updated_at":"2025-04-30T19:32:31.323Z","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-lint\n\nA static analysis linter for many types of source files that looks for i18n problems.\n\nThis i18n linter differs from other static linters in the following ways:\n\n* It can apply different rulesets to different sets of files. This is useful for\n  a number of reasons:\n    * when linting a mono-repo that has different subprojects inside of it\n      and each subproject needs different rules applied to its files\n    * when different sets of files need different rulesets, even within the same file type\n* It can handle any file type\n    * most linters are specific to a programming language and its related files. This linter\n      can read any type of file and apply the appropriate set of rules.\n* Rules can be locale-sensitive\n    * most linters apply the same rules blindly to all files, regardless of the locale\n    * for resource files, it can apply the appropriate locale for each resource individually\n* It can recognize the locale of files from the path name of files\n    * this allows it to apply the locale-sensitive rules automatically. For example, you can apply\n      a rule that checks that the translations in a resource file of a plural resource\n      contain the correct set of plural categories for the target language.\n* It can load plugins\n    * Parsers - you can add parsers for new programming languages or resource file types\n    * Formatters - you can make the output look exactly the way you want\n    * Rules - you can add new rules declaratively or programmatically\n\nSee the [release notes](./docs/ReleaseNotes.md) for details on what is\nnew and what has changed.\n\n## Installation\n\n```\nnpm install ilib-lint\n\nor\n\nyarn add ilib-lint\n```\n\nThen, in your package.json, add a script:\n\n```\n\"scripts\": {\n    \"lint\": \"ilib-lint\"\n}\n```\n\nPlease note: nodejs version 14 or above is required to run this tool, as it\nis written with ESM modules.\n\n## Quick Start\n\nRunning ilib-lint is easy. Just change your directory to the top level directory\nof your project and run it with no parameters and no configuration file. It will\ndo all default behaviours and apply the default rules, which for some projects\nis sufficient:\n\n```\n$ cd myproject\n$ ilib-lint\nilib-lint - Copyright (c) 2022-2024 JEDLsoft, All rights reserved.\nWARN: i18n/ru_RU.properties(45): translation should use the appropriate\nquote style\n  myproject.dialog1.body.text = Нажмите кнопку \"Справка\", чтобы получить\nдополнительную информацию.\n  Rule (locale-quote-style): quote style for the locale \"ru-RU\" should\nbe «text»\n$\n```\n\n## Default Behaviours\n\nThe default behaviour is to recursively search the current directory for all\nxliff files, and then apply all of the built-in resource rules to those files\nand report human-readable results to the standard output.\n\nThe default behaviours are:\n\n* Start in the current directory and recursively find all xliff files\n  underneath there. The xliff file type is built-in to the linter.\n* All built-in rules will be added to the current rule set, and it will\n  instantiate each rule with its default settings.\n* It will use the default set of locales (the top 20 locales on the internet\n  by traffic) with \"en-US\" being the source locale\n* For each file found, it applies each rule in the ruleset.\n  If a file type does not have any rulesets that apply to it,\n  it will be skipped.\n    * the locale of a file can sometimes be gleaned from its path name\n    * for some types of resource files, the locale is documented in\n      the file itself. (eg. xliff or other resource files)\n* Output will be printed on the standard output in human readable form\n\n\n## Command-line Parameters\n\nilib-lint accepts the following command-line parameters:\n\n* help - Print out a help message detailing these command-line parameters\n* config - Give an explicit path to a configuration file instead of trying to\n  find it in the current directory.\n* errorsOnly - Only give information on errors, not warnings. Also, only exit\n  with status 2 if there are errors, and status 0 if there are warnings. This\n  flag allows you to squelch the warnings and only fail a script if there are\n  actual errors.\n* formatter - name the formatter to use to format the results\n* list - list out all the known rulesets and all of the known plugins: parsers,\n  rules, and formatters. This can assist you with creating your own configuration.\n* locales - Locales you want your app to support globally. Value is a comma-separated\n  list of BCP-47 style locale tags. File types can override this list.\n  Default: the top 20 locales on the internet by traffic.\n* progressinfo - whether or not to show progress information while finding and\n  parsing source files.s\n* sourceLocale - locale of the source files or the source locale for resource\n  files. Default: \"en-US\"\n* quiet - Produce no progress output during the run, except for errors running\n  the tool such as the inability to load a plugin. Instead exit with a return\n  value. Zero indicates no errors, and a positive exit value indicates errors.\n* max-errors {number} - specify the maximum number of acceptable errors. If\n  this number is exceeded, the linter will exit with an exit code of 2. The\n  default maximum number is zero.\n* max-warnings {number} - specify the maximum number of acceptable warnings.\n  If the maximum number of errors is not exceeded, but the maximum number of\n  warnings is, the linter will exit with an exit code of 1. The\n  default maximum number is zero.\n* max-suggestions {number} - specify the maximum number of acceptable suggestions.\n  If the maximum number of errors and warnings are not exceeded, but the maximum\n  number of suggestions is, the linter will exit with an exit code of 1. The\n  default maximum number is unlimited. (That is, suggestions will not cause an\n  exit code unless this command-line parameter is given.)\n* min-score {number} - specify the minimum acceptable I18N score for the project.\n  If the minimum score it not reached, the linter will exit with an exit code\n  of 2. There is no default minimum, so the linter will not give an exit code\n  unless this parameter is specified or unless one of the other limits is\n  exceeded.\n\nIf multiple limits are exceeded (maximum number of errors, warnings, or suggestions,\nor minimum I18N score), the exit code will be the most severe amongst them\nall. (Usually \"2\".)\n\n## Exit Status\n\nIf you want to use this linter in a script, you can check for the following\nexit status:\n\n* 0 - no problems or only suggestions found\n* 1 - warnings found\n* 2 - errors found\n\nWhen the `--errorsOnly` flag is given, the program will return 0 unless at least\none error was found.\n\n## Configuration\n\nSee [details](./src/config/README.md).\n\n## Built-in Rules\n\nSome generic rules that apply to many types of files are built-in to ilib-lint.\nThis apply mostly to resource files, such as XLIFF files.\n\nThe built-in rules are:\n\n- [resource-completeness](./docs/resource-completeness.md) - Make sure every resource has a source and\n  a target string\n- [resource-dnt-terms](./docs/resource-dnt-terms.md) - Error if a \"do not translate\" terms is transalted\n- [resource-edge-whitespace](./docs/resource-edge-whitespace.md) - Error if the leading and trailing whitespace\n  in the target does not match the source\n- [resource-icu-plurals](./docs/resource-icu-plurals.md) - Check for ICU-style plurals. Also works with formatjs\n  plurals, as it has the same syntax.\n- [resource-named-params](./docs/resource-named-params.md) - Ensure that named parameters that appear in the source\n  string are also used in the translated string\n- [resource-no-double-byte-space](./docs/resource-no-double-byte-space.md) - Do not use \"double-byte\" whitespace characters\n- [resource-no-fullwidth-digits](./docs/resource-no-fullwidth-digits.md) -Do not use \"full width\" digits\n- [resource-no-fullwidth-latin](./docs/resource-no-fullwidth-latin.md) - Do not use \"full width\" Latin letters (Romaji)\n- [resource-no-fullwidth-punctuation-subset](./docs/resource-no-fullwidth-punctuation-subset.md) - Do not use certain\n  \"full width\" punctuation characters\n- [resource-no-halfwidth-kana-characters](./docs/resource-no-halfwidth-kana-characters.md) - Do not use \"half width\"\n  Japanese kana characters\n- [resource-no-space-between-double-and-single-byte-character](./docs/resource-no-space-between-double-and-single-byte-character.md) - Do not put a space between a double-byte\n  and a single-byte character\n- [resource-no-space-with-fullwidth-punctuation](./docs/resource-no-space-with-fullwidth-punctuation.md) - Do not put spaces before or after certain\n  \"full width\" punctuation characters.\n- [resource-no-translation](./docs/resource-no-translation.md) - Warning the target translation comes back the same as\n  the original source string\n- [resource-quote-style](./docs/resource-quote-style.md) - If the source string has quotes, check that the target\n  string also has quotes and that those quotes are appropriate for the locale\n- [resource-state-checker](./docs/resource-state-checker.md) - Ensure that all resources have a particular state\n  field value, or one of an array of state field values. The parameter for this\n  rule should either be a string or an array of strings that name the allowed\n  values.\n- [resource-unique-keys](./docs/resource-unique-keys.md) - Ensure that the keys are unique within a locale across\n  all resource files\n- [resource-url-match](./docs/resource-url-match.md) - If the source string contains references to URLs, check\n  that the target string also contains references to the same URLs\n- [source-icu-plural-params](./docs/source-icu-plural-params.md) - Make sure the \"one\" category contains the same\nreplacement parameter as the \"other\" category\n- [source-icu-unexplained-params](./docs/source-icu-unexplained-params.md) - Ensure that every replacement parameter\nin the source string is explained in the translator's note\n- [source-no-dashes-in-replacement-params](./docs/source-no-dashes-in-replacement-params.md) - Do not allow dashes\nin the names of replacement parameters\n- [source-no-escaped-curly-braces](./docs/source-no-escaped-curly-braces.md) - Do not put single quotes around\nreplacement parameters\n- [source-no-lazy-plurals](./docs/source-no-lazy-plurals.md) - Do not use the construct \"(s)\" to indicate either\nsingular or plural. Use a real plural string instead.\n- [source-no-manual-currency-formatting](./docs/source-no-manual-currency-formatting.md) - Do not manually format\ncurrency. Use a number formatter instead.\n- [source-no-manual-date-formatting](./docs/source-no-manual-date-formatting.md) - Do not manually format dates.\nUse a date formatter instead.\n- [source-no-manual-percentage-formatting](./docs/source-no-manual-percentage-formatting.md) - Do not manually\nformat percentages. Use a number formatter instead.\n- [source-no-noun-replacement-params](./docs/source-no-noun-replacement-params.md) - Do not use the untranslatable\nconstruct \"the {param}\" or \"a {param}\"\n\n## Writing Plugins\n\nThe linter tool can support plugins that provide parsers, formatters, or rules,\nor any of them at the same time.\n\n## Common Code\n\nAll plugins should import and use the classes in the\n[ilib-lint-common](https://github.com/ilib-js/ilib-lint-common) package.\nThis defines the super classes for each plugin type, as well as a number\nof utility classes and functions.\n\n### Linter Plugins\n\nLinter plugins are simple wrappers around the parser, formatter, and rule\nplugins, which allow the plugin to define multiple plugins. For example, many\nplugins define multiple related rules at the same time which check for\ndifferent aspects of a string.\n\nThe linter plugin should override and implement these three methods:\n\n- getParsers - return an array of classes that inherit from the Parser class\n- getRules - return an array of classes that inherit from the Rule class\n- getRuleSets - return an array of named rule sets that define which rules to use\n- getFormatters - return an array of classes that inherit from the Formatter class\n\nFor rules and formatters, each array entry can be either declarative or\nprogrammatic. See the descriptions below about declarative and programmatic\nplugins.\n\nWhen returning programmatic plugins, make sure to return the actual class\nitself instead of instances of the class. The linter will need to create\nmultiple instances of each class during the run of the program.\n\n### Parsers\n\nThe job of the parser is to convert a source file into an intermediate representation\nthat rules can easily digest. There are a few standard representations that many\nrules use, but your parser and rules can use their own representation, as\nlong as the parser and the rules agree on what that format is. Typically, a\nsophisticated parser will produce something like an abstract syntax tree (AST) that\nthe rules know how to traverse and interpret. The standard representations are\nmuch simpler than that. These parsers should pick a unique name for their\nrepresentation so that the appropriate rules can parse that representation.\n\nThe standard representations are:\n\n- resources - the file is converted into an array of\n  [Resource](https://github.com/iLib-js/ilib-tools-common/blob/main/src/Resource.js)\n  instances\n- lines - the file in converted into a simple array of lines\n- source - the file is not parsed. Instead, the entire text of the file is used to\n  search for problems. (Usually with regular expressions.)\n\nThe resources representation is intended to represent entries in resource files\nsuch as xliff files, gnu po files, or java properties files. Each entry in the\nresource file is represented as an instance of one of the standard resource\nclasses all defined in the\n[ilib-tools-common](https://github.com/ilib-js/ilib-tools-common)\nproject:\n\n- ResourceString - the resource is a single string\n- ResourceArray - the resource is an array of strings\n- ResourcePlural - the resource is a plural string\n\nThe power of a resource file is that resources can contain both a source and a\ntarget string, so the rules are able to check the source strings against the target\nstrings. Regularly, source files only have source strings in them (if any) so\nthe target translations cannot be checked.\n\nParsers should extend the `Parser` class from the `ilib-lint-common` package. The constructor\nfor your class should define the following properties:\n\n- `this.name` - a unique name for this parser\n- `this.description` - a description of this type of parser to display to users\n\nIt should also override the\n[parseData()](https://github.com/iLib-js/ilib-lint-common/blob/main/src/Parser.js)\nmethod which parses a string, and the\n[parse()](https://github.com/iLib-js/ilib-lint-common/blob/main/src/Parser.js)\nmethod, which loads data from the file and then parses it.\n\nYou can see an example of a parser plugin by looking at the gnu PO file parser at\n[ilib-lint-python-gnu](https://github.com/ilib-js/ilib-lint-python-gnu/blob/main/src/POParser.js).\nThat parser interprets a .po file as a resource file and returns a set of\nResource instances.\n\n### Rules\n\nRules interpret the intermediate representation of a file produced by a Parser\nand produce a single\n[Result](https://github.com/iLib-js/ilib-lint-common/blob/main/src/Result.js)\ninstance, an array of Result instances, one for each problem found, or undefined\nif there are no problems found.\n\nThere are two types of rules, declarative and programmatic.\n\nDeclarative rules are simply a list of regular expressions with metadata. The\nlinter searches for matches to those regular expressions and produces Result\ninstances when found. (Or when they are not found in some cases!)\n\nThese can be declared in the config file. (See the example config file above.)\n\nEach declarative rule should have the following properties:\n\n* type (String) - the type of this rule. This may be any of the\n  following:\n    * resource-matcher - check resources in a resource file. The\n      regular expressions that match in the\n      source strings must also match in the target string\n    * resource-source - check resources in a resource file. If\n      the regular expressions match in the source string of a\n      resource, a result will be generated\n    * resource-target - check resources in a resource file. If\n      the regular expressions match in the target string of a\n      resource, a result will be generated\n    * source-checker - Check the text in a source file, such as a\n      java file or a python file. Regular expressions that match\n      anywhere in the source file will generate results\n* name (String) - a unique dash-separated name of this rule.\n  eg. \"resource-url-match\",\n* description (String) - a description of what this rule is trying\n  to do. eg. \"Ensure that URLs that appear in the source string are\n  also used in the translated string\"\n* note (String) - string to use when the regular expression check fails.\n  eg. \"URL '{matchString}' from the source string does not appear in\n  the target string\"\n  Note that you can use `{matchString}` to show the user the string\n  that the regular expression matched in the source but not in the target.\n* regexps (Array.\u003cString\u003e) - an array of regular expressions to match\n  in the source and target strings. If any one of those expressions\n  matches in the source, but not the target, the rule will create\n  a Result that will be formatted for the user.\n* link (String) - an URL to a website with a more complete explanation\n  of the problem that was found and how the problem can be resolved\n  and avoided in the future. Often, this is a link to a markdown file\n  in the docs folder on the github repo for the plugin, but it can be\n  any link you like.\n* severity (String) - the severity of this result if this check fails.\n  This should be one of \"error\", \"warning\", or \"suggestion\".\n    - Errors are typically things that block localization completely,\n      cause exceptions or crashes in code, or which are unacceptable\n      from a localization point of view. Teams should strive for\n      zero errors in their project.\n    - Warnings are things that are not quite as severe as errors\n      and therefore do not block localization or cause crashes, but\n      which should still be fixed to improve the quality of the\n      translations.\n    - Suggestions are things that may not necessarily be wrong, but\n      where a better way exists or where a recommended practice should\n      be followed.\n\nProgrammatic rules are used when the requirements for the rules are more complicated\nthan a simple regular expression string can handle. For example, a rule that checks\nif the target string of a resource has the correct quote style for the target\nlocale first needs to look up what the correct quote style even is in\norder to apply the rule.\n\nIn order to create a rule instance, create a class that extends the\n[Rule](https://github.com/ilib-js/ilib-lint-common/blob/main/src/Rule.js)\nclass in the [ilib-lint-common](https://github.com/ilib-js/ilib-lint-common/) project.\nThe constructor of this class should define the following properties:\n\n- `this.name` - a unique name for this rule\n- `this.description` - a description of this type of rule to display to users\n\nThere are no rules for what to name your Rule, but the Rules written by the ilib-js\norganization generally follow some conventions. Resource checkers start with\n\"resource-\" and source file checkers start with \"source-\". For resource checkers,\nthe word \"match\" is used at the end when checking both the source and target,\n\"source\" is used at the end when checking only the source string, and \"target\"\nwhen checking only the target string. So, \"resource-urls-match\" is a Rule that\nchecks resource files for URLs in both the source and target. You are free to name\nyour rules anything you like or to follow the conventions above. The important\npart is that the name should uniquely identify your Rule so that you can use it\nin config files.\n\nThe rule should also override and implement the getRuleType() method and the\n[match()](https://github.com/iLib-js/ilib-lint-common/blob/main/src/Rule.js) method,\nwhich takes an intermediate representation as a parameter and returns either\na single Result, an array of Result, or undefined.\n\nIf you would like to see an example rule plugin, see the definition of\nthe built-in ICU plural matcher rule:\n[resource-icu-plurals](https://github.com/ilib-js/ilib-lint/blob/main/src/rules/ResourceICUPlurals.js)\nwhich checks resources to make sure that plurals in source and target strings\nhave the correct syntax for ICU and formatjs.\n\n### Rule Sets\n\nRule sets are exactly what they sound like -- a named set that makes it easy\nto use a list of rules with a particular file type.\n\nRule sets can be declared in the config file or can be returned from a plugin.\nBy convention, at least one of the rulesets returned from each plugin typically\nnames all of the rules that that plugin supports. That way, a configuration can\nbe assured of using all the latest available rules when the version of the plugin\nis upgraded, without explicitly updating the config to name all of those new rules.\n\nRule sets should be returned from the getRuleSets method of a plugin which are an\nobject where the properties name the rule sets, and the value of each property is\nanother object that lists the individual rules that are members of that set,\nand their possible parameters/initializers.\n\nExample return value from a call to getRuleSets:\n\n```javascript\n{\n    \"javascript\": {\n        \"source-check-hard-coded-strings\": true,\n        \"source-check-icu-plural-syntax\": {\n            \"enforcement\": \"strict\"\n        }\n    }\n}\n```\n\nIn this example, one rule set \"javascript\" is returned, listing two rules. The\nfirst rule has the value `true` meaning that it is turned on. The second rule\nhas an initializer telling the rule code to strictly enforce the plural\nsyntax. (Each rule defines for itself what parameters/initalizers it accepts.)\n\n### Formatters\n\nFormatters transform a [Result object](https://github.com/iLib-js/ilib-lint-common/blob/main/src/Result.js) into a format that the consumer can use. For the most part, the consumer\nis a human, so the result should be formatted in text so that the user can read\nit easily. Other times, the consumer is another program, so the result should be\nformatted for easy parsing. Formatters can formats the results in any way necessary.\n\nThere are two types of formatters, declarative and programmatic.\n\nDeclarative formatters are simply a template string where properties of the Result\ninstances are formatted into it. These can be declared in the config file. (See the\nexample config file above.)\n\nThe template strings may have any of the following fields from the Result instance\nin them:\n\n- severity\n- pathName\n- lineNumber\n- source\n- highlight\n- id\n\nAdditionally, they may have the following fields from the Rule instance in them:\n\n- ruleDescription\n- ruleName\n- ruleLink\n\nProgrammatic formatters are used when the requirements for formatting are more complicated\nthan a simple template string can handle. For example, a CSV formatter would have to make\nsure that fields in a CSV file are escaped properly to conform to CSV syntax, and would\ninclude escaping code in it.\n\nIn order to create a formatter instance, create a class that extends the\n[Formatter](https://github.com/ilib-js/ilib-lint-common/blob/main/src/Formatter.js)\nclass in the [ilib-lint-common](https://github.com/ilib-js/ilib-lint-common/) project.\nThe constructor of this class should define the following properties:\n\n- `this.name` - a unique name for this formatter\n- `this.description` - a description of this type of formatter to display to users\n- `this.link` - (optional) a link to a web page that gives a more complete explanation\n  of the rule and how to resolve the problem it found\n\nThe formatter should also override and implement the\n[format()](https://github.com/iLib-js/ilib-lint-common/blob/main/src/Formatter.js) method,\nwhich takes a Result instance as a parameter and returns a formatted string.\n\nIf you would like to look at an example formatter plugin, see the definition of\nthe built-in default formatter\n[ansi-console-formatter](https://github.com/ilib-js/ilib-lint/blob/main/src/formatters/AnsiConsoleFormatter.js)\nwhich formats a Result for colorful output on an ANSI console.\n\n## Example Plugin\n\nYou can take a look at the [ilib-lint-python](https://github.com/ilib-js/ilib-lint-python)\nplugin as a working example of ilib-lint plugin. It implements some rules that\ncheck the various types of substitution parameters that python/django and\ngnu gettext support.\n\nAdditionally, there is a [sample python project](https://github.com/iLib-js/ilib-samples/tree/main/lint)\nthat uses the ilib-lint-python plugin. It has purposeful errors built into it which\nviolate the rules implemented in the plugin so that the linter will produce some output.\nClone the project, cd to the lint directory, run `npm install`, and then `npm run lint`\nto see the results.\n\n## I18N Score\n\nAt the end of each run, the i18n tool can generate a score that gives you an idea numerically\nof how ready your project is for localization. The score goes from 0 to 100 where 0 means\nthat your project is not localization ready at all, and 100 means it is completely ready for\nlocalization.\n\nMany projects do not have a perfect 100 score, and that can be acceptable. It is still possible\nto produce a reasonably localized version of the project without achieving 100. The recommended\ngoal for each project should be to continually increase the score as development proceeds up to\na minimal acceptable threshold that your team agrees to with your localization team. Nicely\nlocalized projects typically have a score in the range of 80 to 100. Often teams will decide\nthat they want a maximum of zero errors, but allow up to N number of warnings, and M number of\nsuggestions.\n\n### Calculations\n\nThere are actually a number of things calculated at the end of the run:\n\n- percentage of source files containing errors, warnings, suggestions, and total problems\n- percentage of source lines containing errors, warnings, suggestions, and total problems\n- the overall score across the whole project\n\nThe overall score takes into account the following factors:\n\n- the number of source files\n- the number of lines in each source file\n- the number and type of results from applying rules\n- the number of rules being applied\n- the scores from subprojects\n\nErrors weigh heaviest in the calculations, followed by warnings, and finally suggestions. That\nis, a project with 5 errors in it will have a lower score than one with 5 warnings or 5\nsuggestions.\n\nAs such, it should be noted that the I18N score is not a percentage, but a\nunit-less score which may change over time as the linter changes, even if your project does\nnot change. The relative movement of the score is the most important thing to look at to\nsee if the project is improving. As new rules are implemented and set into your configuration\nafter updating a newer version of the linter or installing new plugins, the score for a\nproject may go down for a while until the problems manifested by the new rules are resolved. This\ndoes not mean the quality of your project has gone down, just that new things have been\nidentified to work on.\n\nWhen your project contains subprojects, each subproject will get its own report and I18N\nscore. The reports and scores for subprojects will be rolled up to the main project, which\nwill have an overall federated score across the current project and all all subprojects. This\nway, you will be able to measure the progress in libraries, services, or subprojects independently\nof your main project.\n\nFor example, your project may use a mono-repo which contains \"frontend\", \"backend\", and \"services\"\nsubprojects within it, each being developed by different teams. They can each have their\nown I18N scores and the overall project has a federated score based on the scores of the\nsubprojects.\n\n### Using the Score as a CI/CD Pipeline Check\n\nThe linter now includes command-line flags where you can specify minimums and maximums\nfor various numbers. The linter will exit with an exit code if the minimums or maximums are\nnot satisfied. You can use this exit code to determine if your CI/CD pipeline has failed or\nsucceeded.\n\nSee the section above on command-line parameters for details on these.\n\n## Migrating Plugins\n\nSee the [migration doc](./docs/migration.md) for more information about upgrading your\nilib-lint plugins from v1 of ilib-lint to v2.\n\n## License\n\nCopyright © 2022-2024, JEDLSoft\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\nSee the License for the specific language governing permissions and\nlimitations under the License.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filib-js%2Filib-lint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filib-js%2Filib-lint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filib-js%2Filib-lint/lists"}