{"id":13413572,"url":"https://github.com/vorlif/spreak","last_synced_at":"2025-03-14T19:32:45.157Z","repository":{"id":39321663,"uuid":"490044472","full_name":"vorlif/spreak","owner":"vorlif","description":"Flexible translation and humanization library for Go, based on the concepts behind gettext.","archived":false,"fork":false,"pushed_at":"2023-12-09T15:33:14.000Z","size":1041,"stargazers_count":54,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-07-31T20:52:34.169Z","etag":null,"topics":["gettext","go","golang","i18n","internationalization","localization","translation"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vorlif.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}},"created_at":"2022-05-08T20:09:34.000Z","updated_at":"2024-07-16T13:49:13.000Z","dependencies_parsed_at":"2024-01-08T15:34:55.643Z","dependency_job_id":null,"html_url":"https://github.com/vorlif/spreak","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vorlif%2Fspreak","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vorlif%2Fspreak/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vorlif%2Fspreak/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vorlif%2Fspreak/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vorlif","download_url":"https://codeload.github.com/vorlif/spreak/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221498771,"owners_count":16833059,"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":["gettext","go","golang","i18n","internationalization","localization","translation"],"created_at":"2024-07-30T20:01:43.489Z","updated_at":"2024-10-26T05:31:06.447Z","avatar_url":"https://github.com/vorlif.png","language":"Go","funding_links":[],"categories":["Natural Language Processing","自然语言处理","Bot Building","Microsoft Office"],"sub_categories":["Translation","翻译"],"readme":"# Spreak ![Test status](https://github.com/vorlif/spreak/workflows/Test/badge.svg) [![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![PkgGoDev](https://pkg.go.dev/badge/github.com/vorlif/spreak)](https://pkg.go.dev/github.com/vorlif/spreak) [![Go Report Card](https://goreportcard.com/badge/github.com/vorlif/spreak)](https://goreportcard.com/report/github.com/vorlif/spreak) [![codecov](https://codecov.io/gh/vorlif/spreak/branch/main/graph/badge.svg?token=N1O0ZE1OFW)](https://codecov.io/gh/vorlif/spreak) ![MinVersion](https://img.shields.io/badge/Go-1.19+-blue)\n\nFlexible translation and humanization library for Go, based on the concepts behind gettext. Requires Go 1.19+.\n\n### Why another library?\n\nThere are already many good libraries for Go, which allow localizing an application.\nHowever, I always came to a point where I was dissatisfied.\nEither they use a self defined format, which could not be edited with common tools.\nSome libraries only support one language at a time or are using a lot of mutexes.\nAnd no tool could easily extract the strings to be translated.\nI wanted to solve these problems for myself, and so spreak was born.\n\n### Features\n\n* Built-in support for `po`, `mo` and [`json`](./examples/features/jhttptempl) files\n* [Direct support for humanization](#package-humanize-)  of Go data structures\n* Support for `fs.FS` (e.g. `embed`)\n* Goroutine-safe and lock free through immutability\n* [Powerful extractor](https://github.com/vorlif/xspreak#xspreak) for strings to simplify the localization process\n  (with **support for templates**)\n* [Support](https://pkg.go.dev/github.com/vorlif/spreak#hdr-Plurals)\n  for [gettext](https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html)\n  and [CLDR v44](https://cldr.unicode.org/index/cldr-spec/plural-rules) plural rules.\n* Support of bilingual and monolingual formats\n\n### Usage\n\nUsing spreak is easy. First, use go get to install the latest version of the library.\n\n```shell\ngo get -u github.com/vorlif/spreak\n```\n\nAfter that, spreak offers you a comprehensive interface to load and query your translations.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/x/text/language\"\n\n\t\"github.com/vorlif/spreak\"\n\t\"github.com/vorlif/spreak/localize\"\n)\n\nfunc main() {\n\t// Create a bundle that loads the translations for the required languages.\n\t// Typically, you only need one bundle in an application.\n\tbundle, err := spreak.NewBundle(\n\t\t// Set the language used in the program code/templates\n\t\tspreak.WithSourceLanguage(language.English),\n\t\t// Set the path from which the translations should be loaded\n\t\tspreak.WithDomainPath(spreak.NoDomain, \"./locale\"),\n\t\t// Specify the languages you want to load\n\t\tspreak.WithLanguage(language.German, language.Spanish, language.Chinese),\n\t)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Create a Localizer to select the language to translate.\n\tt := spreak.NewLocalizer(bundle, language.Spanish)\n\n\t// Translate\n\tfmt.Println(t.Get(\"Hello world\"))\n\tfmt.Println(t.NGetf(\"I have %d dog\", \"I have %d dogs\", 2, 2))\n\tfmt.Println(t.Localize(GetPlanet()))\n\n\t// Output: \n\t// Hola Mundo\n\t// Tengo 2 perros\n\t// No conozco ningún planeta\n}\n\nfunc GetPlanet() *localize.Message {\n\treturn \u0026localize.Message{\n\t\tSingular: \"I do not know any planet\",\n\t\tPlural:   \"I do not know any planets\",\n\t}\n}\n```\n\n### Extract strings\n\nStrings for the translations can be extracted via the [command line program xspreak](https://github.com/vorlif/xspreak).\nUse a [pre-built binary](https://github.com/vorlif/xspreak/releases/latest) or install it from source:\n\n```bash\ngo install github.com/vorlif/xspreak@latest\n```\n\nTests installation with:\n\n```bash\nxspreak --help\n```\n\nxspreak extracts the strings from the program code and creates a template which can be used for new translations.\nBefore you extract your strings, you have to decide on a format.\n\nIt can either create a `.pot` (PO Templates) file in po format or a `.json` file.\nIf you are not sure which format to use, I would recommend you to use `po` format,\nbecause it is supported by almost all translation programs, which makes your life and the life of your translators much\neasier.\n\nWith `-D` you specify the path to your source code and with `-p` the one where the translation template should be saved.\n\n```bash\n# for .pot\nxspreak -D path/to/source/ -p path/to/source/locale\n# for .json\nxspreak -D path/to/source/ -p path/to/source/locale -f json\n```\n\nThis creates a new `.pot` or `.json` file representing the translation template.\n\n### Translate\n\n**po files**\n\nThe generated POT files can be easily imported by most translation tools.\nIf you are dealing with Po files for the first time,\nI recommend the application [Poedit](https://poedit.net/) for a quick start.\n\nAfter translation `.po` or `.mo` files are generated, which are used by spreak for looking up translations.\nAttention, do not translate the `.pot` file directly, as this is only a template.\n\n**json files**\n\nYou can open and edit the JSON files with any text editor.\nThe extracted template always uses only the plural categories `one` and `other`. \nTo create a template with the plural categories suitable for your language, you can use xspreak.\n\n```bash\nxspreak merge -i locale/template.json -o locale/de.json -l de\n```\n\n### Update translation files\n\n\u003e :warning: It would be wise before making any move to **keep a backup**.\n\nWhen you add, edit or delete text in your program code, you should also update the translation files.\nTo achieve this, you must first update the template:\n\n```bash\n# for .pot\nxspreak -D path/to/source/ -p path/to/source/locale\n# for .json\nxspreak -D path/to/source/ -p path/to/source/locale -f json\n```\n\nThis creates a new `.pot` or `.json` file representing the *new* translation template.\n\n**po files**\n\nFor PO files, almost every translation tool offers the possibility to update the files from a POT file.\nWith Poedit you can do it via `Translation -\u003e Update from POT file`.\nIf you use the gettext utilities, you can use `msgmerge -U es.po template.pot`.\nFor all other tools, it is worth taking a look at the documentation.\n\n**json files**\n\nFor JSON files, xspreak offers a simple way to update the translation files.\n\n```bash\nxspreak merge -i locale/template.json -o locale/de.json -l de\n```\n\nThis copies new keys and existing translations from `template.json` to `de.json` and deletes keys from `de.json`\nthat are not present in `template.json`.\n\n### Structure translations\n\nHow you structure the files with the translations is up to you.\nAssuming you load the domain `\"helloworld\"` from the path `\"./locale\"` and the language `language.Spanish`\n\n```go\nspreak.WithDomainPath(\"helloworld\", \"./locale\"),\nspreak.WithLanguage(language.Spanish),\n```\n\nThen spreak searches for the following files by default\n\n```text\n./locale/es/helloworld.po\n./locale/helloworld/es.po\n./locale/es.po\n./locale/LC_MESSAGES/es/helloworld.po\n```\n\nWhere `es` is an example from the list `[es-ES, es_ES, spa, es]` and the file extension `.po` is an example from the\nlist `[po, mo, json]`.\nIf you don't like this behavior, you can implement your own [`Resolver`](examples/features/resolver/main.go).\nFor special cases you can also implement your own [`Loader`](examples/features/loaders/main.go).\n\n### How to use in tests?\n\nJust create a `Bundle` without options.\nThis will never return an error and can be used to create `Localizer` which then simply return the input.\n\n```go\nbundle, _ := spreak.NewBundle()\nt := spreak.NewLocalizer(bundle, language.English)\n```\n\n### What's next\n\n* Read what you can extract with [xspreak](https://github.com/vorlif/xspreak#xspreak)\n* Take a look in the [examples folder](./examples) for more examples of using spreak.\n* Use it!\n\n## Package humanize [![PkgGoDev](https://pkg.go.dev/badge/github.com/vorlif/spreak/humanize)](https://pkg.go.dev/github.com/vorlif/spreak/humanize)\n\nThe `humanize` package provides a collection of functions to convert Go data structures into a human-readable format.\nIt was widely adapted from the [Django project](https://github.com/django/django) and also uses the Django translations.\nIt should therefore be noted that the translations are under\nthe [Django's 3-clause BSD license](https://raw.githubusercontent.com/django/django/main/LICENSE).\n\nTo use the `humanize` package, you first need to load the languages you want to use.\nYou can find a list of all supported languages under [humanize/locale/](humanize/locale)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"golang.org/x/text/language\"\n\n\t\"github.com/vorlif/spreak/humanize\"\n\t\"github.com/vorlif/spreak/humanize/locale/ar\"\n\t\"github.com/vorlif/spreak/humanize/locale/es\"\n\t\"github.com/vorlif/spreak/humanize/locale/zhHans\"\n)\n\nfunc main() {\n\t// Load the translations for the desired languages\n\tcollection := humanize.MustNew(\n\t\thumanize.WithLocale(es.New(), ar.New(), zhHans.New()),\n\t)\n\n\t// Create a humanizer.\n\t// A humanizer features a collection of humanize functions for a language.\n\th := collection.CreateHumanizer(language.English)\n\n\t// Uses the functions...\n\tfmt.Println(h.Intword(1_000_000_000))\n\t// Output: 1.0 billion\n\n\tfmt.Println(h.NaturalDay(time.Now()))\n\t// Output: today\n\n\tt := time.Now().Add(5 * time.Minute)\n\tfmt.Println(h.NaturalTime(t))\n\t// Output: 5 minutes from now\n\n\td := -80 * time.Hour\n\tfmt.Println(h.TimeSince(d))\n\t// Output: 3 days, 8 hours\n\n\t// ... for different languages\n\th = collection.CreateHumanizer(language.Spanish)\n\tfmt.Println(h.TimeSince(d))\n\t// Output: 3 días, 8 horas\n}\n```\n\nA collection of all functions and further examples can be found in\nthe [documentation](https://pkg.go.dev/github.com/vorlif/spreak/humanize).\n\n### Add translations\n\nIf you would like to add a translation or add a new language, **do not do so in this repository**.\nThe translations in this repository are automatically generated from the Django translations and additions should also\nbe made there.\nUse the following link to do so: https://www.transifex.com/django/django/.\nFor all non-translation related errors, this repository must be used.\n\n## License\n\nspreak is available under the MIT license. See the [LICENSE](LICENSE) file for more info.\nThe translations of the `humanize` packages are licensed\nunder [Django's BSD license](https://raw.githubusercontent.com/django/django/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvorlif%2Fspreak","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvorlif%2Fspreak","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvorlif%2Fspreak/lists"}