Skip to content

Commit

Permalink
chore(i18n): add us translation (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
plastikfan committed Mar 1, 2023
1 parent 26933b7 commit 0375404
Show file tree
Hide file tree
Showing 10 changed files with 344 additions and 17 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ ginkgo.report
test-options*.json
test-state*.json
*.log
i18n/out/*
i18n/temp/*
39 changes: 39 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,42 @@ tasks:
cover:
cmds:
- ginkgo --json-report ./ginkgo.report -coverpkg=./... -coverprofile=./coverage/coverage.out -r

# === i18n =================================================

clear:
cmds:
- rm ./i18n/out/* --recursive

# extract i18m messages
extract:
cmds:
- goi18n extract -format json -sourceLanguage "en-GB" -outdir ./i18n/out/

# new translation
newt:
deps: [extract]
cmds:
- touch ./i18n/out/l10n/translate.en-US.json

# derive a translation from the default
merge:
cmds:
- goi18n merge -format json -sourceLanguage "en-GB" -outdir ./i18n/out ./i18n/out/active.en-GB.json ./i18n/out/l10n/translate.en-US.json

# update existing translations
# after running this task, the translation file generated will contain only the
# new translations. Update the active file, with the new translations.
# Also, need to copy the default file (active.en-GB.json) back into ./i18n/default
update:
deps: [extract]
cmds:
- goi18n merge -format json -sourceLanguage "en-GB" -outdir ./i18n/out ./i18n/out/active.en-GB.json ./i18n/deploy/active.en-US.json

# run this after manual translation has occurred to integrate it back into the
# translation file. Unfortunately, this task doesn't work properly, because it
# does not include the hashes. Without this task, the new translations must be manually
# added to the active translation file (active.en-US.json).
accept:
cmds:
- goi18n merge -format json -sourceLanguage "en-US" -outdir ./i18n/temp ./i18n/out/translate.en-US.json ./i18n/deploy/active.en-US.json
67 changes: 67 additions & 0 deletions Test/data/l10n/test.active.en-US.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"failed-to-read-directory-contents.extendio.nav": {
"description": "Failed to read directory contents from the path specified",
"hash": "sha1-f752d658bce68d1352780ed1c97c5728ed1ad123",
"other": "failed to read directory contents '{{.Path}}' (reason: {{.Reason}})"
},
"failed-to-resume-from-file.extendio.nav": {
"description": "Failed to resume traverse operation from the resume file specified",
"hash": "sha1-1a87a71c8cbcc40d326990fff9ede9c67bddb9dd",
"other": "failed to resume from file '{{.Path}}' (reason: {{.Reason}})"
},
"localisation.general.extendio": {
"description": "Localisation",
"hash": "sha1-053e15971b8d428c47cdb902f90c4fcecc72e253",
"other": "localization"
},
"internationalisation.general.extendio": {
"description": "Internationalisation",
"hash": "sha1-8dd7952545d8104150f6d66d3e0f3c650b44c072",
"other": "internationalization"
},
"invalid-config.entry.extendio.nav": {
"description": "Invalid entry specified in config at the location specified",
"hash": "sha1-b40de177a90f9f632ae822874eed02311c2021fd",
"other": "invalid entry '{{.Value}}' specified in config at {{.At}}"
},
"invalid-resume-strategy.internal.extendio.nav": {
"description": "Invalid resume strategy specified",
"hash": "sha1-db8a9607a285f29d80e2969a306b0e31e8efa032",
"other": "invalid resume strategy '{{.Value}}' specified"
},
"missing-callback.internal.extendio": {
"description": "Missing callback (internal error)",
"hash": "sha1-233cf9593871e12228fe66b1eab40a861c87c6df",
"other": "missing callback (internal error)"
},
"missing-custom-filter-definition.config.extendio": {
"description": "Missing custom filter definition (config error)",
"hash": "sha1-fe56c6ea6888fbc45d84b2452e2e396915651f59",
"other": "missing custom filter definition at {{.At}} (config error)"
},
"not-a-directory.extendio.nav": {
"description": "File system path is not a directory",
"hash": "sha1-a1035e6df966ae710ac7210a6739821a99902b04",
"other": "file system path '{{.Path}}', is not a directory"
},
"sort-fn-failed.internal.extendio.nav": {
"description": "Sort function failed (internal error)",
"hash": "sha1-bea43015691a8aa9aad2d7fff8951bebd4ea4f93",
"other": "sort function failed (internal error)"
},
"terminate-traverse.extendio.nav": {
"description": "Traversal terminated",
"hash": "sha1-b3b621ace1bb4371932bcec9c1eb2dbc0f038df1",
"other": "terminate traversal: '{{.Reason}}'"
},
"third-party-error.extendio": {
"description": "These errors are generated by dependencies that don't support localisation",
"hash": "sha1-e6d0dab3fa4d2b429a4a5c7d2bb282bfe5401cbe",
"other": "third party error: '{{.Error}}'"
},
"unknown-marshal-format.config.extendio.nav": {
"description": "Unknown marshal format specified",
"hash": "sha1-4d269888af5da71a116e2856ae22020a2300b40b",
"other": "unknown marshal format {{.Format}} specified at {{.At}}"
}
}
54 changes: 54 additions & 0 deletions i18n/default/active.en-GB.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"failed-to-read-directory-contents.extendio.nav": {
"description": "Failed to read directory contents from the path specified",
"other": "failed to read directory contents '{{.Path}}' (reason: {{.Reason}})"
},
"failed-to-resume-from-file.extendio.nav": {
"description": "Failed to resume traverse operation from the resume file specified",
"other": "failed to resume from file '{{.Path}}' (reason: {{.Reason}})"
},
"internationalisation.general.extendio": {
"description": "Internationalisation",
"other": "internationalisation"
},
"invalid-config.entry.extendio.nav": {
"description": "Invalid entry specified in config at the location specified",
"other": "invalid entry '{{.Value}}' specified in config at {{.At}}"
},
"invalid-resume-strategy.internal.extendio.nav": {
"description": "Invalid resume strategy specified",
"other": "invalid resume strategy '{{.Value}}' specified"
},
"localisation.general.extendio": {
"description": "Localisation",
"other": "localisation"
},
"missing-callback.internal.extendio": {
"description": "Missing callback (internal error)",
"other": "missing callback (internal error)"
},
"missing-custom-filter-definition.config.extendio": {
"description": "Missing custom filter definition (config error)",
"other": "missing custom filter definition at {{.At}} (config error)"
},
"not-a-directory.extendio.nav": {
"description": "File system path is not a directory",
"other": "file system path '{{.Path}}', is not a directory"
},
"sort-fn-failed.internal.extendio.nav": {
"description": "Sort function failed (internal error)",
"other": "sort function failed (internal error)"
},
"terminate-traverse.extendio.nav": {
"description": "Traversal terminated",
"other": "terminate traversal: '{{.Reason}}'"
},
"third-party-error.extendio": {
"description": "These errors are generated by dependencies that don't support localisation",
"other": "third party error: '{{.Error}}'"
},
"unknown-marshal-format.config.extendio.nav": {
"description": "Unknown marshal format specified",
"other": "unknown marshal format {{.Format}} specified at {{.At}}"
}
}
67 changes: 67 additions & 0 deletions i18n/deploy/active.en-US.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"failed-to-read-directory-contents.extendio.nav": {
"description": "Failed to read directory contents from the path specified",
"hash": "sha1-f752d658bce68d1352780ed1c97c5728ed1ad123",
"other": "failed to read directory contents '{{.Path}}' (reason: {{.Reason}})"
},
"failed-to-resume-from-file.extendio.nav": {
"description": "Failed to resume traverse operation from the resume file specified",
"hash": "sha1-1a87a71c8cbcc40d326990fff9ede9c67bddb9dd",
"other": "failed to resume from file '{{.Path}}' (reason: {{.Reason}})"
},
"localisation.general.extendio": {
"description": "Localisation",
"hash": "sha1-053e15971b8d428c47cdb902f90c4fcecc72e253",
"other": "localization"
},
"internationalisation.general.extendio": {
"description": "Internationalisation",
"hash": "sha1-8dd7952545d8104150f6d66d3e0f3c650b44c072",
"other": "internationalization"
},
"invalid-config.entry.extendio.nav": {
"description": "Invalid entry specified in config at the location specified",
"hash": "sha1-b40de177a90f9f632ae822874eed02311c2021fd",
"other": "invalid entry '{{.Value}}' specified in config at {{.At}}"
},
"invalid-resume-strategy.internal.extendio.nav": {
"description": "Invalid resume strategy specified",
"hash": "sha1-db8a9607a285f29d80e2969a306b0e31e8efa032",
"other": "invalid resume strategy '{{.Value}}' specified"
},
"missing-callback.internal.extendio": {
"description": "Missing callback (internal error)",
"hash": "sha1-233cf9593871e12228fe66b1eab40a861c87c6df",
"other": "missing callback (internal error)"
},
"missing-custom-filter-definition.config.extendio": {
"description": "Missing custom filter definition (config error)",
"hash": "sha1-fe56c6ea6888fbc45d84b2452e2e396915651f59",
"other": "missing custom filter definition at {{.At}} (config error)"
},
"not-a-directory.extendio.nav": {
"description": "File system path is not a directory",
"hash": "sha1-a1035e6df966ae710ac7210a6739821a99902b04",
"other": "file system path '{{.Path}}', is not a directory"
},
"sort-fn-failed.internal.extendio.nav": {
"description": "Sort function failed (internal error)",
"hash": "sha1-bea43015691a8aa9aad2d7fff8951bebd4ea4f93",
"other": "sort function failed (internal error)"
},
"terminate-traverse.extendio.nav": {
"description": "Traversal terminated",
"hash": "sha1-b3b621ace1bb4371932bcec9c1eb2dbc0f038df1",
"other": "terminate traversal: '{{.Reason}}'"
},
"third-party-error.extendio": {
"description": "These errors are generated by dependencies that don't support localisation",
"hash": "sha1-e6d0dab3fa4d2b429a4a5c7d2bb282bfe5401cbe",
"other": "third party error: '{{.Error}}'"
},
"unknown-marshal-format.config.extendio.nav": {
"description": "Unknown marshal format specified",
"hash": "sha1-4d269888af5da71a116e2856ae22020a2300b40b",
"other": "unknown marshal format {{.Format}} specified at {{.At}}"
}
}
12 changes: 8 additions & 4 deletions i18n/localizer-factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ func (f LocalizerFactory) create(li *LanguageInfo) *i18n.Localizer {
bundle.RegisterUnmarshalFunc("json", json.Unmarshal)

if li.Current != li.Default {
// TODO: consider changing this, too rigid, active may not be liked by client,
// they should be able to control the name of the translation file.
//
filename := fmt.Sprintf("%v.active.%v.json", li.Name, li.Current)
filename := lo.TernaryF(li.Name == "",
func() string {
return fmt.Sprintf("active.%v.json", li.Current)
},
func() string {
return fmt.Sprintf("%v.active.%v.json", li.Name, li.Current)
},
)
resolved, _ := filepath.Abs(li.Path)

directory := lo.TernaryF(li.Path != "",
Expand Down
59 changes: 49 additions & 10 deletions i18n/messages.error.nav.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// due-ly noted, but if translations are important, then we
// have to live with this problem unless another approach
// is available. Its not really recommended to provide foreign
// translations for external packages as this creates as
// translations for external packages as this creates an
// undesirable coupling, but the option is there just in case.
// To ameliorate api surface area issue, limit error definitions
// to those errors that are intended to be displayed to
Expand Down Expand Up @@ -42,13 +42,58 @@ import (
// can be wrapped (errors.Wrap), providing content in the
// required but library un-supported language.
//
// There does NOT need to be a translation file for the default language
// as the default language is what's implemented in code, here in
// message files (messages.error.nav.go). Having said that, we
// still need to create a file for the default language as that file
// is used to create translations. This default file will not be
// be part of the installation set.
// ===> checked in as i18n/default/active.en-GB.json
//
// 1) This file is automatically processed to create the translation
// files, currently only 'active.en-US.json' by running:
// $ goi18n extract -format json -sourceLanguage "en-GB" -out ./out
// ---> creates i18n/out/active.en-GB.json (i18n/default/active.en-GB.json)
// ===> implemented as task: extract
//
// 2) ... Create an empty message file for the language that you want
// to add (e.g. translate.en-US.json).
// ---> when performing updates, you don't need to create the empty file, use the existing one
// ---> check-in the translation file
// ===> this has been implemented in the extract task
//
// 3) goi18n merge -format json active.en.json translate.en-US.json -outdir <dir>
// (goi18n merge -format <json|toml> <default-language-file> <existing-active-file>)
//
// existing-active-file: when starting out, this file is blank, but must exist first.
// When updating existing translations, this file will be the one that's already
// checked-in and the result of manual translation (ie we re-named the translation file
// to be active file)
//
// current dir: ./extendio/i18n/
// $ goi18n merge -format json -sourceLanguage "en-GB" -outdir ./out ./out/active.en-GB.json ./out/l10n/translate.en-US.json
//
// ---> creates the translate.en-US.json in the current directory, this is the real one
// with the content including the hashes, ready to be translated. It also
// creates an empty active version (active.en-US.json)
//
// ---> so the go merge command needs the translate file to pre-exist
//
// 4) translate the translate.en-US.json and copy the contents to the active
// file (active.en-US.json)
//
// 5) the translated file should be renamed to 'active' version
// ---> so 'active' files denotes the file that is used in production (loaded into bundle)
// ---> check-in the active file

type ExtendioTemplData struct{}

func (td ExtendioTemplData) SourceId() string {
return EXTENDIO_SOURCE_ID
}

// ====================================================================

// ❌ FailedToReadDirectoryContents

// FailedToReadDirectoryContentsTemplData failed to resume using file
Expand All @@ -62,7 +107,7 @@ func (td FailedToReadDirectoryContentsTemplData) Message() *i18n.Message {
return &i18n.Message{
ID: "failed-to-read-directory-contents.extendio.nav",
Description: "Failed to read directory contents from the path specified",
Other: "failed to read directory contents '{{.Path}}' (reason: {{.REASON}})",
Other: "failed to read directory contents '{{.Path}}' (reason: {{.Reason}})",
}
}

Expand Down Expand Up @@ -113,7 +158,7 @@ func (td FailedToResumeFromFileTemplData) Message() *i18n.Message {
return &i18n.Message{
ID: "failed-to-resume-from-file.extendio.nav",
Description: "Failed to resume traverse operation from the resume file specified",
Other: "failed to resume from file '{{.Path}}' (reason: {{.REASON}})",
Other: "failed to resume from file '{{.Path}}' (reason: {{.Reason}})",
}
}

Expand Down Expand Up @@ -495,12 +540,6 @@ func QueryTerminateTraverseError(target error) bool {

// ❌ ThirdPartyError

// ====================================================================

// This file is automatically processed to create the active.en.json
// by running:
// $ goi18n extract -format json

// ThirdPartyErrorTemplData third party un-translated error
type ThirdPartyErrorTemplData struct {
ExtendioTemplData
Expand Down Expand Up @@ -546,7 +585,7 @@ type UnknownMarshalFormatTemplData struct {
func (td UnknownMarshalFormatTemplData) Message() *i18n.Message {
return &i18n.Message{
ID: "unknown-marshal-format.config.extendio.nav",
Description: "Unknown marshal format specified in config",
Description: "Unknown marshal format specified",
Other: "unknown marshal format {{.Format}} specified at {{.At}}",
}
}
Expand Down
Loading

0 comments on commit 0375404

Please sign in to comment.