DEV Community

Cover image for How to localize Go app with go-i18n and Localazy
Petr HodnΓ½ for Localazy

Posted on • Originally published at localazy.com

How to localize Go app with go-i18n and Localazy

Are you looking for a straightforward approach how to localize your Go app into other languages? Seek no more - Localazy will take care of it for you.

Localazy is a universal translation management platform that supports a wide variety of formats and frameworks. It is a platform tailor-made for developers.

Thanks to the Localazy CLI, you can easily set up the download and upload commands to be part of your automation once and never be bothered by key extraction, file merging, and looking up which translations are still missing ever again.

Or you can just upload everything once, translate and download back manually. The choice is yours, and the localization possibilities are endless.

🚩 Localization with go-i18n

This article will show you how to prepare your Go project for localization using a very popular go-i18n package.

You will learn how to connect your Go app to Localazy, include your source keys in your main language in the application, and resolve the messages by their keys for both singular and plural variants in your primary language as well as others. Let's dive into it!

πŸ™„ tldr;

  • sign up for Localazy ,
  • create an app with English as source language and Use community translations (ShareTM) option enabled,
  • select Go integration option and install Localazy CLI,
  • include go-i18n in your app,
  • create localazy.json in root and paste in and modify the configuration,
  • create locales folder and in it create en.json. Add any translation key-value pair,
  • run localazy upload,
  • in Localazy, add any language. Then review it and accept the suggested phrases,
  • run localazy download and check locales folder for the new locale,
  • run the app go run main.go

πŸ•ΉοΈ Sign up and app creation

First of all, let's set up a new Localazy account and create a new application. In this article, we'll use English as the source language, but you can generally choose any other. Make sure that the Use community translations (ShareTM) option is enabled.

ShareTM is highly accurate translation memory. Thanks to it, most new applications have as much as 50 % of strings automatically pre-translated into 80+ languages.

Proceed to create the app. Then, select Go on the integration screen. We'll use the powerful CLI tool to manage the upload and download of phrases. Installation is available for Linux, macOS, and Windows.

Note the read and write keys from step 2 somewhere. We'll need them shortly.

Localazy.com Integration Page

πŸ› οΈ Set up Go app

If you don’t want to follow the step-by-step guide here, you can take a look at the finished repo. Otherwise, stay awhile and listen.

Configuration

First of all, initialize a Go module which is a core tool for managing dependencies. Since we'll be using Go packages, it just makes dependency management easier.

Just run:

go mod init go-i18n-example
Enter fullscreen mode Exit fullscreen mode

The next thing to do is to integrate Localazy. Create localazy.json in the root of your application and paste the following configuration. Use the write and read keys from the step 2 of the integration guide page.

{
    "writeKey": "your-write-key",
    "readKey": "your-read-key",

    "upload": {  
      "type": "json",
      "files": "locales/en.json",
      "features": ["plural_object"]  
    },

    "download": {
      "files": "locales/${lang}.json"
    }
}
Enter fullscreen mode Exit fullscreen mode

The upload section is for locating the source language file and uploading all of the source keys. Note the plural_object option, this configures to recognize plural variants using key-value approach.

The download section is configured to download the published languages in Localazy back to the locales folder under the language's tag name.

However, the English language file is still missing. So create en.json within the locales folder. Since we’ve set English to be the source language, this file will contain the source keys for our application. You can fill in any key-value pair you like. I’ll add this:

{
    "listen": "Stay a while and listen",
    "person": {
        "one": "person",
        "other": "people"
    }
}
Enter fullscreen mode Exit fullscreen mode

Go code

Got the pun? Go (as verb) code?πŸ˜… Anyways, create a main.go file in the root folder and paste in the following code.

// main.go
package main

import (
    "encoding/json"
    "fmt"

    "github.com/nicksnyder/go-i18n/v2/i18n"
    "golang.org/x/text/language"
)

func initLocalizer(langs ...string) *i18n.Localizer {
    // Create a new i18n bundle with English as default language.
    bundle := i18n.NewBundle(language.English)

    // Register a json unmarshal function for i18n bundle.
    // This is to enable usage of json format
    bundle.RegisterUnmarshalFunc("json", json.Unmarshal)

    // Load source language
    bundle.LoadMessageFile("./locales/en.json")

    // Initialize localizer which will look for phrase keys in passed languages
    // in a strict order (first language is searched first)
    // When no key in any of the languages is found, it fallbacks to default - English language
    localizer := i18n.NewLocalizer(bundle, langs...)

    return localizer
}
Enter fullscreen mode Exit fullscreen mode

We have prepared a factory function for initialization of localizer object from the go-i18n package that is responsible for looking up strings in selected language by it's key.

As you can see, the initLocalizer function is defined as variadic which means it can take an arbitrary number of arguments. That is convenient since you may want, in certain scenarios, to look up the string in several languages, especially when you're just searching for regional variants.

Now, let's add the rest of the example code that will print a single message that combines the simple key and the plural key we've defined earlier in the json localization file.

You could also use other formats if you prefer, such as TOML or YAML.

I will already predefine Latin American Spanish as the first desired language and then *Spanish * as a first possible fallback. We don't have those translations yet, but we will shortly.

// main.go

...

func main() {
    //
    localizer := initLocalizer(
        language.LatinAmericanSpanish.String(),
        language.Spanish.String(),
    )

    simpleMessage, _ := localizer.Localize(&i18n.LocalizeConfig{
        MessageID: "listen", // source key identifier
    })

    pluralMessage, _ := localizer.Localize(&i18n.LocalizeConfig{
        DefaultMessage: &i18n.Message{ID: "person"}, // another source key identifier
        PluralCount:    2, // would use "one" variant if the count was 1
    })

    fmt.Println(simpleMessage + ", " + pluralMessage)
}
Enter fullscreen mode Exit fullscreen mode

Your project structure should look like this at this point:

.
β”œβ”€β”€ locales
β”‚   └── en.json
β”œβ”€β”€ go.mod
β”œβ”€β”€ go.sum
β”œβ”€β”€ localazy.json
└── main.go
Enter fullscreen mode Exit fullscreen mode

You can already test it out. Run go run main.go and you should see Stay a while and listen, people message in your terminal. Since the localizer could not find those keys in either Spanish variant, it has fallen back to the English language.

~/go-i18n-example $ go run main.go

Stay a while and listen, people
Enter fullscreen mode Exit fullscreen mode

β†ͺ️ Uploading and downloading strings

Upload using CLI

Let's upload the English file to Localazy. From the root folder, run the following command

localazy upload -s
Enter fullscreen mode Exit fullscreen mode

The -s argument stands for simulate. It is a good practice to test out the configuration without uploading anything to assure that nothing unexpected happens (such as some of the key-value pairs are incorrectly matched and override each other).

The output should be something along these lines, depending on the CLI version.

Localazy CLI, v1.4.5
Command-line tool for the Localazy platform.

Read more information at https://localazy.com/docs/cli

Parameters:
  - deprecate missing: false
  - import as new: false
  - force current: false
  - filter source: true
  - app version: 0
  - groups: (default only)
  - folder: .

Processing files...

locales/en.json
(file: file.json, lang: inherited, type: json)

Verifying...

Validating...

Done.
Enter fullscreen mode Exit fullscreen mode

And now, let's let upload it for real.

localazy upload
Enter fullscreen mode Exit fullscreen mode

Translate and review with the power of ShareTM

Refresh your app page and you should see the English language on the list. Open the Add languages tab and there you find a couple of languages with info about the percentage of automated translations.

It is possible that you will see either 50 % or 100 %. The automated matching with ShareTM improves all the time and it's likely that thanks to this article you would have all the strings automatically translated. How cool is that? πŸ™‚

Localazy.com - ShareTM - Software Localization

One way or another, look up Spanish and Latin American Spanish and add them to your app. You'll see that there is a review button. Every time ShareTM provides a translation suggestion, it will have candidate status. This means that it will be ready for review, and any reviewer can either approve it or decline it. Go ahead and approve the suggested text(s).

In case that the ShareTM did not translate 100 %, come back to the languages list and notice that the review button now reads translate. Localazy recognizes that there is nothing to review but still something to translate, so it offers you the next most likely action in one click.

Translate the remaining texts (you may use one of the suggestions on the translation page). This time you do not need to go through the review process since you are a trusted translator as owner by default, so the translation is immediately approved.

Use newly translated languages

It's time to go back to the Go project. πŸ™ƒ

localazy download
Enter fullscreen mode Exit fullscreen mode

With this command, you'll download all the recently accepted translations and newly added languages. In the locales folder, we can see there are newly created es.json and es-419.json files.

This how your final project structure should look like:

.
β”œβ”€β”€ locales
β”‚   β”œβ”€β”€ en.json
β”‚   β”œβ”€β”€ es-419.json
β”‚   └── es.json
β”œβ”€β”€ go.mod
β”œβ”€β”€ go.sum
β”œβ”€β”€ localazy.json
└── main.go
Enter fullscreen mode Exit fullscreen mode

Let's include these translations in the application. Add the following lines to the initLocalizer function just below where you load the English file.

bundle.LoadMessageFile("./locales/es-419.json")
bundle.LoadMessageFile("./locales/es.json")
Enter fullscreen mode Exit fullscreen mode

Now when you rerun the app, you'll see that Localazy correctly translated the strings to Spanish.

~/go-i18n-example $ go run main.go

QuΓ©date un rato y escucha, Personas
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Closing words

I hope you've enjoyed this sneak peek at what Localazy can do for you and understood how easy it is to start localizing any Go app with it. If you would like to play around with the prototype, you can check it out on Replit. The whole git repository is available on GitHub.

If you have any questions, just join us on our Discord for a chat.

Discussion (0)