Skip to content

Simple command-line utility to localize your Golang applications.

License

Notifications You must be signed in to change notification settings

infastin/go-l10n

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-l10n

go-l10n is a command-line utiltity that generates Golang files from localization files defined in YAML, JSON or TOML format.

It supports strings with arguments that come from Golang code and variables defined within messages, and allows to create different messages depending on the value of the arguments.

Installation

Install it using go command:

go install github.com/infastin/go-l10n@latest

Writing messages

Simplest message possible looks like this:

Welcome: "Welcome, traveler!"

The message identifier can consist of any characters you want. Here it is Welcome.

If you want to display arbitrary string instead of traveler, you can make use of arguments, that will be passed from Golang:

Welcome: "Welcome, ${name}!"

Arguments are contained inside of ${...} blocks. Argument names in generated code will be the same as in YAML code. So if you have argument ${very_beautiful_name}, in Go it also will be very_beautiful_name. Argument names can only contain Latin letters (a-zA-Z).

In order to escape $ just write it twice.

All arguments are strings by default. But you can change it by prefixing argument name with one of the following formats:

  • s:string
  • f:float64
  • d:int
  • v: - any
  • S:fmt.Stringer

You can also format arguments using format specification similar to Golang's fmt package.

Format consists of:

  1. Flags
  2. Width
  3. Precision
  4. Type specifier (ones specified above)
  5. Golang format specifier for the type (for example, it can be x for integers to output them in hex format)

Flags, width, precision and format specifiers are all the same as in Golang's fmt package.

Format goes before argument name and is separated from it with ::

BankAccount: "You have $$${+.3f:money} dollars in your bank account."

If you want your message to look different depending on some integral argument, you can use plural block:

YouAreLate:
  plural:
    arg: "count"
    one: "You are 1 minute late."
    other: "You are ${count} minutes late."

plural block consists of 5 fields:

  • arg — name of the argument depending on the value of which different messages will be returned
  • zero - message when arg equals zero
  • one - message when arg equals one
  • many - message when arg is more than one
  • other - message to be returned when nothing above is true or not specified

arg is required, and the argument specified in this field is forced to be int.

You can rewrite example above using variables. Variables are defined within a message and only visible within it:

YouAreLate:
  variables:
    minutes:
      plural:
        arg: "count"
        one: "minute"
        other: "minutes"
  string: "You are ${count} &{minutes} late."

Variables are contained within &{...} blocks. Variables don't support formatting. Variable names can only contain Latin letters and underscores (a-zA-Z_).

In order to escape & just write it twice.

You can use arguments inside of variable values:

YouAreLate:
  variables:
    minutes:
      plural:
        arg: "count"
        zero: "0 minutes"
        one: "1 minute"
        other: "${count} minutes"
  string: "You are &{minutes} late."

Also variables can be simple strings (even though it's not very useful):

HelloWorld:
  variables:
    world: "World"
  string: "Hello, &{world}!"

Everything shown above can also be done in JSON or TOML.

Generating

Now you write a bunch of messages in files withing one directory whose names match this regexp pattern:

([a-z_]+)\.([a-z_]+)\.(yaml|yml|json|toml)

Or, to put it more simply: {{.Name}}.{{.Lang}}.{{.Ext}}.

Also you can change the regexp pattern with -p, --pattern=PATTERN flag to go-l10n command. But it must contain three groups in the following order:

  1. Name — will be used when generating files, but doesn't really matter
  2. Language — en, de, es, etc
  3. Extension — yaml, yml, json or toml

Now you run a command:

go-l10n -d YOUR_DIRECTORY -o OUTPUT_DIRECTORY

If your messages are correct, it will generate a bunch of Go files in the output directory with the package name being l10n. You can change it with -P, --package=NAME flag.

The file that you wanna look into is l10n.go:

// Code generated by go-l10n; DO NOT EDIT.

package l10n

type Localizer interface {
	BankAccount(money float64) string
	YouAreLate() string
}

var mapLangToLocalizer = map[string]Localizer{
	"en": en_Localizer{},
	"ru": ru_Localizer{},
}

var Supported = []string{
	"en",
	"ru",
}

func New(lang string) (loc Localizer, ok bool) {
	loc, ok = mapLangToLocalizer[lang]
	return loc, ok
}

func Language(loc Localizer) string {
	switch loc.(type) {
	case en_Localizer:
		return "en"
	case ru_Localizer:
		return "ru"
	default:
		return ""
	}
}

Slice Supported contains all supported languages. With New function you can get yourself Localizer for a given language. And with Language function you can get the language from Localizer.

Once you obtain Localizer, you can simply call its methods, which are named exactly like messages defined in your localization files, with the arguments that you've specified, that are named exactly as you defined them, to get yourself a localized message.

License

MIT

About

Simple command-line utility to localize your Golang applications.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages