{"id":16615909,"url":"https://github.com/ko1nksm/sh-i18n","last_synced_at":"2025-10-29T19:30:33.831Z","repository":{"id":65560211,"uuid":"594016977","full_name":"ko1nksm/sh-i18n","owner":"ko1nksm","description":"Fully portable gettext library for POSIX-compliant shell scripts","archived":false,"fork":false,"pushed_at":"2023-02-03T11:53:51.000Z","size":118,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-10T20:51:44.363Z","etag":null,"topics":["bash","busybox","dash","gettext","i18n","ksh","mksh","posix","yash","zsh"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ko1nksm.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},"funding":{"github":"ko1nksm"}},"created_at":"2023-01-27T11:59:55.000Z","updated_at":"2023-10-20T11:22:27.000Z","dependencies_parsed_at":"2023-02-15T23:31:04.400Z","dependency_job_id":null,"html_url":"https://github.com/ko1nksm/sh-i18n","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Fsh-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Fsh-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Fsh-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ko1nksm%2Fsh-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ko1nksm","download_url":"https://codeload.github.com/ko1nksm/sh-i18n/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238874438,"owners_count":19545190,"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":["bash","busybox","dash","gettext","i18n","ksh","mksh","posix","yash","zsh"],"created_at":"2024-10-12T02:11:13.410Z","updated_at":"2025-10-29T19:30:33.454Z","avatar_url":"https://github.com/ko1nksm.png","language":"Shell","funding_links":["https://github.com/sponsors/ko1nksm"],"categories":[],"sub_categories":[],"readme":"# sh-i18n\n\nFully portable gettext library for POSIX-compliant shell scripts.\n\n## Introduction\n\nsh-i18n is an easy to use and highly portable internationalization library for shell scripts. It supports all POSIX-compliant shells and can run in any environment. It is based on the gettext API and only commands `gettext` and `ngettext` are required. These API and commands will be standardized in POSIX.1-2023 (Issue 8). sh-i18n works with OS standard commands. If these commands are not installed, fallback to work with default messages.\n\nThis is an alternative library that aims to replace [GNU `gettext.sh`](https://www.gnu.org/software/gettext/manual/html_node/sh.html). It is currently in **beta release**. We will try to maintain the specifications as much as possible, but may change them in the future.\n\n## sh-i18n vs GNU gettext.sh\n\n|                                                      | sh-i18n          | GNU gettext.sh             |\n| ---------------------------------------------------- | ---------------- | -------------------------- |\n| Portability                                          | ✅ Fully portable | Depends on GNU `gettext`   |\n| POSIX shells (modern sh, dash, bash and others)      | ✅ All supported  | ✅ All supported (probably) |\n| Bourne shell (obsolete sh)                           | No               | ✅ Yes (probably)           |\n| Use only POSIX (Issue 8) commands                    | ✅ Yes            | No (depends on `envsubst`) |\n| Environment without `gettext`, `ngettext` commands   | ✅ Works          | Does not work              |\n| Shorthand (`_`, `n_`, `s_`, `ns_`, `p_`, `np_`)      | ✅ Available      | Nothing                    |\n| `gettext_noop` (`N_`) and similar                    | ✅ Available      | Nothing                    |\n| `sgettext`, `nsgettext`                              | ✅ Available      | Nothing                    |\n| `pgettext`, `npgettext` (GNU gettext extensions)     | ✅ Available      | ✅ Available                |\n| Dollar-Single-Quotes (`$'...'`) for MSGID            | ✅ All supported  | Shell dependent            |\n| Parameter field (`%1$s`)                             | ✅ All supported  | Shell dependent            |\n| Locale-dependent number separator (`%'d`)            | ✅ All supported  | Shell dependent            |\n| Locale-dependent decimal point symbols (`.` `,` `٫`) | ✅ All supported  | Shell dependent            |\n| Faster than GNU gettext.sh                           | ✅ Yes            | No                         |\n\n## Tutorial\n\n```sh\n#!/bin/sh\n\nset -eu\n\n. \"${0%/*}/lib/i18n.sh\"\n\nexport TEXTDOMAIN=\"sh-i18n\"\nexport TEXTDOMAINDIR=\"${0%/*}/locale\"\n\n# Used in some XSI-compliant environments (e.g. OpenIndiana)\nexport NLSPATH=\"${0%/*}/locale/%l/LC_MESSAGES/%N.mo\"\n\necho \"==== Basic ====\"\n_ 'Hello World.'\n_ 'Hello, %s.' -- Ken\necho\n\necho \"==== Plural forms ====\"\nn_ 'Here is %d apple.' 'Here are %d apples.' 2\nn_ '%2$s has %1$d apple.' '%2$s has %1$d apples.' 1 Ken\necho\n\necho \"==== Using backslash escape sequences ====\"\n_ $'Here is a tab =\u003e\\t\u003c=.'\n_ $'It\\047s a small world.\\n' -n\necho\n\necho \"==== Locale-dependent numeric values ====\"\n_ \"The distance from the earth to the sun is %'d km.\" 149597870000\n_ \"PI is %f.\" 3.1415926535\necho\n\necho \"==== Use \\$'...' for msgid that begin with \\$. ====\"\n_ $'$100 is about %\\047d Japanese yen.' $((100 * 130))\n```\n\n```console\n$ LANG=ja_JP.UTF-8 ./example.sh\n==== Basic ====\nこんにちは世界。\nこんにちは、Ken。\n\n==== Plural forms ====\nここに 2 個のリンゴがあります。\nKen は 1 個のリンゴを持っています。\n\n==== Using backslash escape sequences ====\nここにはタブ =\u003e\t\u003c= があります。\n世界は小さい。\n\n==== Using decimal separator ====\n地球から太陽までの距離は 149,597,870,000 km です。\n円周率は 3.141593 です。\n\n==== Use $'...' for msgid that begin with $. ====\n$100 ドルは日本円でおそよ 13,000 円です。\n```\n\n**NOTE:** If it cannot be translated, the message catalog may need to be reworked.\n\n```sh\nmsgfmt -o locale/ja/LC_MESSAGES/sh-i18n.mo po/ja.po\n```\n\n## Requirements\n\n- **POSIX shell**\n  - dash, bash, ksh, zsh, etc\n- **`gettext` and `ngettext` commands**\n  - These commands are standardized in POSIX issue 8\n  - If not installed, fall back to the implementation without translation\n- `msgfmt` command (Recommendation)\n- `xgettext` with shell script support (Development)\n\n`gettext`, `ngettext`, `msgfmt`, and `xgettext` are standardized in POSIX.1-2023 (Issue 8).\n\nShells that we have decided not to support due to shell bugs:\n\n- pdksh (v5.2.14 99/07/13.2), posh (0.14.1)\n  - bug: `set -- abc a; echo ${1#\"$2\"}` =\u003e falsely empty\n- ksh88 (Version M-11/16/88), ksh93 (Version JM 93t+ 2009-05-01)\n  - bug: \"@: parameter not set\" (It works if you don't `set -u`)\n- bash (2.04)\n  - bug: Segmentation fault\n\n## API\n\nGettext Functions\n\n| Basic                                   | Context (p)                                 | Scope (s)                                   |\n| --------------------------------------- | ------------------------------------------- | ------------------------------------------- |\n| [i18n_print ( _ )](#i18n_print--_-)     | [i18n_pprint ( p_ )](#i18n_pprint--p_-)     | [i18n_sprint ( s_ )](#i18n_sprint--s_-)     |\n| [i18n_nprint ( n_ )](#i18n_nprint--n_-) | [i18n_npprint ( np_ )](#i18n_npprint--np_-) | [i18n_nsprint ( ns_ )](#i18n_nsprint--ns_-) |\n| [i18n_gettext](#i18n_gettext)           | [i18n_pgettext](#i18n_pgettext)             | [i18n_sgettext](#i18n_sgettext)             |\n| [i18n_ngettext](#i18n_ngettext)         | [i18n_npgettext](#i18n_npgettext)           | [i18n_nsgettext](#i18n_nsgettext)           |\n\nGettext Helper (experimental)\n\n- [i18n_build_array](#i18n_build_array)\n- [i18n_set_array](#i18n_set_array)\n- [i18n_gettext_noop ( N_ )](#i18n_gettext_noop--n_-)\n- [i18n_gettext_s2v ( S_ )](#i18n_gettext_s2v--s_-)\n- [i18n_gettext_a2p ( @_ )](#i18n_gettext_a2p--_-_)\n- [i18n_gettext_a2v ( V_ )](#i18n_gettext_a2v--v_-)\n- [i18n_gettext_a2a ( A_ )](#i18n_gettext_a2a--a_-)\n- [i18n_gettext_a2aa ( AA_ )](#i18n_gettext_a2aa--aa_-)\n\nUtilities\n\n- [i18n_printf](#i18n_printf)\n- [i18n_printfln](#i18n_printfln)\n- [i18n_echo](#i18n_echo)\n- [i18n_detect_decimal_point](#i18n_detect_decimal_point)\n\nEnvironment Variables\n\n- [I18N_GETTEXT, I18N_NGETTEXT](#i18n_gettext-i18n_ngettext)\n- [I18N_PRINTF](#i18n_printf-1)\n\n### MSGID\n\nMSGID is the key used for translation. For example, `_ \"Hello World\"`, `_ 'Hello World'`, `_ $'Hello World'` would be the MSGID of the message `Hello World`. If no translation is found, the MSGID is output as is.\n\nIt is not possible to include variables or command substitutions in the MSGID. To be precise, the translation itself works, but `xgettext`, which generates the message catalog, does not recognize it as a string to be translated.\n\n```sh\n# Wrong MSGIDs\n_ \"Hello${TAB}World\"\n_ \"Hello$(printf '\\t')World\"\n```\n\n`$'...'` is a shell feature called \"Dollar-Single-Quotes\" that will be standardized in POSIX Issue 8. When newlines or tabs are included in A `$'...'`, it can be written with escape sequences like `$'FOO\\tBAR\\n'`.\n\nDollar-Single-Quotes is a feature that is already available in many shells, such as bash, but not yet in dash. However, sh-i18n implements a workaround so that Dollar-Single-Quotes can be used in shells that do not support Dollar-Single-Quotes as far as MSGID is concerned (The feature does not make Dollar-Single-Quote available to the entire shell script). If Dollar-Single-Quotes is not used, it could be written as follows, but it would be difficult to read.\n\n```sh\n_ 'Hello\tWorld' # It contains a tab character\n_ 'Hello\nWorld' # It contains a newline character\n\n_ $'Hello\\tWorld\\n' # Legible\n```\n\n#### Dollar-Single-Quotes Limitations\n\nsh-i18n has the unique feature of being able to use Dollar-Single-Quotes with MSGID, which is useful for including tabs and newlines in messages. However, the following Limitations are made so that shells that support Dollar-Single-Quotes and shells that do not support Dollar-Single-Quotes can be written in the same way.\n\n**If the first character of the MSGID is `$`, it cannot be written as `'MSGID'` or `\"MSGID\"`.** If the first character is `$`, you must write `$'$ is dollar'`. This is because shells that do not support dollar-single quoting use the leading `$` to determine whether to interpret backslash escape sequences.\n\n```sh\n#  Shells that do not support $'...' cannot distinguish between\n_ '$ is dollar'\n_ $'is dollar'\n\n# It should be written as follows\n_ $'$ is dollar'\n```\n\n**Cannot split a string into multiple quotes.** The entire message must be written in a single Dollar-Single-Quote. This is because the decision to interpret backslash escape sequences is made only at the beginning of the string.\n\n```sh\n# The entire message must be written in one $'...'\n_ $'Hello world\\n'    # Correct\n_ $'Hello '$'world\\n' # Wrong\n_ $'Hello ''world\\n'  # Wrong\n```\n\n**If you want to include single quotes in a string, you cannot use `\\'`.** You must use `\\47` or `\\047` instead.\n\n```sh\n# Wrong\n_ $'It\\'s a small world\\n'\n\n# Correct\n_ $'It\\47s a small world\\n'\n_ $'It\\047s a small world\\n'\n```\n\nDespite this limitation, we believe it is more convenient to make Dollar-Single-Quote available because messages often contain tabs and newlines.\n\n### Gettext Functions\n\n#### i18n_print ( _ )\n\n```txt\n_ MSGID [-n | --] [ARGUMENT]...\ni18n_print MSGID [-n | --] [ARGUMENT]...\n```\n\nIn many other programming languages, `_` is an alias for the `gettext` function, but in sh-i18n it is an alias for the `i18n_print` shell function. The `i18n_print` shell function performs variable expansion, similar to the `eval_gettext` shell function in `gettext.sh`.\n\nThe second argument is a flag, specify `-n` or `--`. If `-n` is specified, suppresses output of trailing a newline. If `--` is specified, a newline is output. `--` is optional, but we recommend not omitting it given the possibility that the value of ARGUMENT is `--`.\n\nIf the MSGID contains the `%` format, the arguments are expanded and the value passed in ARGUMENT is assigned. See `i18n_printf` for about format.\n\n#### i18n_nprint ( n_ )\n\n```txt\nn_ MSGID MSGID-PLURAL [-n | --] N [ARGUMENT]...\ni18n_nprint MSGID MSGID-PLURAL [-n | --] N [ARGUMENT]...\n```\n\nUse `n_` to internationalize messages for plurals. It is an alias for the `i18n_nprint` shell function. The `i18n_nprint` shell function performs variable expansion, similar to the `eval_ngettext` shell function in `gettext.sh`.\n\nThe third argument is a flag, specify `-n` or `--`. If `-n` is specified, suppresses output of trailing a newline. If `--` is specified, a newline is output. `--` is optional. Since the next argument is numeric, `--` can safely be omitted.\n\nIf the fourth argument is `1`, MSGID is used as the message; if it is not `1`, MSGID-PLURAL is used.\n\nIf the MSGID contains the `%` format, the arguments are expanded and the value passed in ARGUMENT is assigned. See `i18n_printf` for about format.\n\n#### i18n_sprint ( s_ )\n\n```txt\ns_ SCOPE'|'MSGID [-n | --] [ARGUMENT]...\ni18n_sprint SCOPE'|'MSGID [-n | --] [ARGUMENT]...\n```\n\n#### i18n_nsprint ( ns_ )\n\n```txt\nns_ SCOPE'|'MSGID MSGID-PLURAL [-n | --] N [ARGUMENT]...\ni18n_nsprint SCOPE'|'MSGID MSGID-PLURAL [-n | --] N [ARGUMENT]...\n```\n\n#### i18n_pprint ( p_ )\n\n```txt\np_ MSGCTXT MSGID [-n | --] [ARGUMENT]...\ni18n_pprint MSGCTXT MSGID [-n | --] [ARGUMENT]...\n```\n\n#### i18n_npprint ( np_ )\n\n```txt\nnp_ MSGCTXT MSGID MSGID-PLURAL [-n | --] N [ARGUMENT]...\ni18n_npprint MSGCTXT MSGID MSGID-PLURAL [-n | --] N [ARGUMENT]...\n```\n\n#### i18n_gettext\n\n```txt\ni18n_gettext VARNAME MSGID\n```\n\nGet the specified MSGID and assign it to the variable specified by VARNAME. Options are not available and escape sequences are not interpreted　as with `gettext -E`.\n\n#### i18n_ngettext\n\n```txt\ni18n_ngettext VARNAME MSGID MSGID-PLURAL N\n```\n\nGet the specified MSGID and assign it to the variable specified by VARNAME. Options are not available and escape sequences are not interpreted　as with `ngettext -E`.\n\n#### i18n_sgettext\n\n```txt\ni18n_sgettext VARNAME SCOPE'|'MSGID\n```\n\n#### i18n_nsgettext\n\n```txt\ni18n_nsgettext VARNAME SCOPE'|'MSGID MSGID-PLURAL N\n```\n\n#### i18n_pgettext\n\n```txt\ni18n_pgettext VARNAME MSGCTXT MSGID\n```\n\n#### i18n_npgettext\n\n```txt\ni18n_npgettext VARNAME MSGCTXT MSGID MSGID-PLURAL N\n```\n\n### Gettext Helpers\n\nUsed to assign MSGID to a variable.\n\n#### i18n_build_array\n\n```txt\ni18n_build_array VARNAME\n```\n\nUsed to build variable arrays, arrays, and associative arrays. See below.\n\n```sh\ntypeset -a ary\ni18n_build_array ary\n{\n  A_ \"Array 1\"\n  A_ \"Array 2\"\n  A_ \"Array 3\"\n}\n\nfor i in \"${ary[@]}\"; do\n  _ \"$i\"\ndone\n```\n\n#### i18n_set_array\n\n```txt\ni18n_build_array VARIABLE\n```\n\nUsed to make positional parameters from an array of variables. Please refer to the `i18n_gettext_a2v` ( `V_` ) example.\n\n#### i18n_gettext_noop ( N_ )\n\n```txt\nN_ MSGID\n```\n\nIt works like the `N_` macro in other languages, but is difficult to use in the shell for two reasons:\n\n- Consecutive trailing newlines disappear when used with command substitution\n- Command substitution is poor performance\n\nHowever, the following example works fine.\n\n```sh\nvar=$(N_ \"Apple\")\n_ \"$var\"\n\nset -- \"$(N_ \"Apple\")\" \"$(N_ \"Banana\")\" \"$(N_ \"Orange\")\"\nfor i in \"$@\"; do\n  _ \"$i\"\ndone\n\nary=(\"$(N_ \"Apple\")\" \"$(N_ \"Banana\")\" \"$(N_ \"Orange\")\")\nfor i in \"${ary[@]}\"; do\n  _ \"$i\"\ndone\n```\n\n#### i18n_gettext_s2v ( S_ )\n\n```txt\nS_ VARNAME MSGID\n```\n\nStore the MSGID to the variable.\n\n```sh\nS_ var \"Hello World.\"\n_ \"$var\"\n```\n\n#### i18n_gettext_a2p ( @_ )\n\n```txt\n@_ MSGID\n```\n\nAdd MSGID to the position parameters.\n\n```sh\nset --\n{\n  @_ \"Positional Parameters 1\"\n  @_ \"Positional Parameters 2\"\n  @_ \"Positional Parameters 3\"\n}\nfor i in \"$@\"; do\n  _ \"$i\"\ndone\n```\n\n**NOTE** Because of the dependence on `alias` command, please execute `shopt -s expand_aliases` in bash to make `alias` available.\n\n#### i18n_gettext_a2v ( V_ )\n\n```txt\nV_ MSGID\n```\n\nStores multiple MSGIDs in a single variable. When used, use `i18n_set_array` to set it to the position parameters.\n\n```sh\nvar=''\ni18n_build_array var\n{\n  V_ \"Variable Array 1\"\n  V_ \"Variable Array 2\"\n  V_ \"Variable Array 3\"\n}\ni18n_set_array \"$var\"\nfor i in \"$@\"; do\n  _ \"$i\"\ndone\n```\n\n**NOTE** Because of the dependence on `alias` command, please execute `shopt -s expand_aliases` in bash to make `alias` available.\n\n#### i18n_gettext_a2a ( A_ )\n\n```txt\nA_ MSGID\n```\n\nStores multiple MSGIDs in a single array. Requires array support in the shell.\n\n```sh\ntypeset -a ary\ni18n_build_array ary\n{\n  A_ \"Array 1\"\n  A_ \"Array 2\"\n  A_ \"Array 3\"\n}\nfor i in \"${ary[@]}\"; do\n  _ \"$i\"\ndone\n```\n\n#### i18n_gettext_a2aa ( AA_ )\n\n```txt\nAA_ KEY MSGID\n```\n\nStores multiple MSGIDs in a single associative array. Requires associative array support in the shell.\n\n```sh\ntypeset -A aary\ni18n_build_array aary\n{\n  AA_ key1 \"Associative Array 1\"\n  AA_ key2 \"Associative Array 2\"\n  AA_ key3 \"Associative Array 3\"\n}\nfor i in \"${aary[@]}\"; do\n  _ \"$i\"\ndone\n```\n\n### Utilities\n\n#### i18n_printf\n\n```txt\ni18n_printf FORMAT [ARGUMENT]...\n```\n\nThe values passed in ARGUMENT is expanded according to FORMAT. It internally executes the `printf` command and basically interprets the same format as the `printf` command, but with the following differences.\n\n- Do not interpret backslash escape sequences (only % format is interpreted)\n- Supports positional variable references with the format `\u003cnumber\u003e$`\n- Support for output grouping numbers by the `'` flag (e.g. `%'d`)\n  - If the `printf` implementation does not support the `'` flag, it is ignored\n- Arguments remaining after FORMAT consumes arguments are ignored\n- If the argument referenced by FORMAT does not exist, the format remains in place\n\n#### i18n_printfln\n\n```txt\ni18n_printfln FORMAT [ARGUMENT]...\n```\n\nSame as `i18n_printf` except for the addition of a newline at the end of the output.\n\n#### i18n_echo\n\n```txt\ni18n_echo STRING\n```\n\nThis function is provided as a transition from `gettext.sh`. Those who don't need it don't need to use it. It has the same functionality as the function set in `the $echo` variable of `gettext.sh`, outputting the first argument and newline and not interpreting backslash escape sequences.\n\nIf you want, you can have it do the equivalent of `$echo` by doing the following\n\n```txt\necho='i18n_echo'\n$echo foo\n```\n\nFor more information on `$echo`, see [here](https://www.gnu.org/software/gettext/manual/html_node/gettext_002esh.html).\n\n#### i18n_detect_decimal_point\n\n```txt\ni18n_detect_decimal_point STRING\n```\n\nRe-detect locale-dependent decimal point symbols.\n\n## Environment Variables\n\n### I18N_GETTEXT, I18N_NGETTEXT\n\nSet this environment variable if you want to use different implementations of `gettext` and `ngettext`. It must be set before loading `i18n.sh`.\n\n```sh\nif type ggettext \u003e/dev/null 2\u003e\u00261; then\n  I18N_GETTEXT=ggettext\nfi\n\n. i18n.sh\n```\n\n### I18N_PRINTF\n\nSet this environment variable if you want to use different implementations of `printf`. It must be set before loading `i18n.sh`.\n\n```sh\nI18N_PRINTF=/usr/bin/printf\n\n. i18n.sh\n```\n\n## Notes on using the xgettext command\n\nTo create a message catalog, see [here](https://www.gnu.org/software/gettext/manual/html_node/index.html).\n\nSince the messages to be translated are defined by keywords that differ from the standard, an option to add the keywords must be specified.\n\n```sh\n# To add only shorthands as keywords\nxgettext -k_:1 -kn_:1,2 -ks_:1 -kns_:1,2 -kp_:1c,2 -knp_:1c,2,3 \\\n  -kN_ -kS_:2 -k@_ -kV_ -kA_ -kAA_:2 example.sh\n\n# To add all shorthands and functions as keywords\nxgettext \\\n  -k_:1 -kn_:1,2 -ks_:1 -kns_:1,2 -kp_:1c,2 -knp_:1c,2,3 \\\n  -kN_ -kS_:2 -k@_ -kV_ -kA_ -kAA_:2 \\\n  -ki18n_gettext:2 -ki18n_ngettext:2,3 \\\n  -ki18n_sgettext:2 -ki18n_nsgettext:2,3 \\\n  -ki18n_pgettext:2c,3 -ki18n_nsgettext:2c,3,4 \\\n  -ki18n_gettext_noop -ki18n_gettext_s2v:2 \\\n  -ki18n_gettext_a2v -ki18n_gettext_a2a -ki18n_gettext_a2aa:2 \\\n  example.sh\n\n# In POSIX, -K option is standardized instead of -k option.\n# (I don't know of any implementation that can use the -K option)\nxgettext -K _:1 -K n_:1,2 example.sh\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fko1nksm%2Fsh-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fko1nksm%2Fsh-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fko1nksm%2Fsh-i18n/lists"}