How to localize Go app with go-i18n and Localazy
Tags: tutorial, localization, i18n, go
Published: 2021-07-21 10:52:30

**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](https://localazy.com/dictionary/translation-management-system-tms) that supports a wide variety of [formats and frameworks](https://localazy.com/integrations). It is a platform tailor-made for developers.

Thanks to the [Localazy CLI](https://localazy.com/docs/cli/installation), 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 ](https://localazy.com/dictionary/localization) possibilities are endless.

## 🚩 Localization with go-i18n
This article will show you how to prepare your [Go project](https://localazy.com/go) for localization using a very popular [go-i18n](https://github.com/nicksnyder/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](https://localazy.com/register) ,
- [create an app](https://localazy.com/my/create) with English as source language and *Use community translations (ShareTM)* option enabled,
- select [Go](https://localazy.com/go) integration option and install [Localazy CLI](https://localazy.com/docs/cli/installation),
- include [go-i18n](https://github.com/nicksnyder/go-i18n) in your app,
- create `localazy.json` in root and paste in and modify the [configuration](https://localazy.com/docs/cli/quick-start-go),
- 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](https://localazy.com/register) and [create a new application](https://localazy.com/my/create). 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](https://localazy.com/docs/general/what-is-localazy-sharetm) is highly accurate [translation memory](https://localazy.com/dictionary/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](https://localazy.com/docs/cli/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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wo8yb7g9fw7i4n0mfw2j.png)
 

## 🛠️ 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](https://github.com/localazy/go-i18n-example). 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
``` 

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"
    }
}
``` 

The upload section is for locating the source language file and uploading all of the source keys. Note the `plural_object`  [option](https://localazy.com/docs/cli/json-format#defined-as-object), 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"
    }
}
``` 

### 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
}
``` 

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](https://gobyexample.com/variadic-functions) 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)
}
``` 

Your project structure should look like this at this point:


```
.
├── locales
│   └── en.json
├── go.mod
├── go.sum
├── localazy.json
└── main.go
``` 

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
```

## ↪️ 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
```

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.
``` 

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


```
localazy upload
``` 

### 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](https://localazy.com/docs/general/what-is-localazy-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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i94tfybb0hsgy3dppg0x.png)
 
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
``` 

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
``` 

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")
``` 

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
``` 

## ✔️ 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](https://replit.com/@DanCharvt/go-i18n-example#main.go). The whole git repository is available on [GitHub](https://github.com/localazy/go-i18n-example). 

If you have any questions, just join us on our [Discord](https://discord.gg/sQucDznuMp) for a chat.