Home

Translations with Firebase

February 7, 2017

At my place of work we were doing translations with json files and key value pairs.

eg. en-US.json

{
  "this_key": "Translates to this"
}

This is really nice and simple, nothing really wrong with it. It does have a few downsides though. It can be annoying to get translations from people who know the language. Typically we would convert the json to csv and give them that. Then you would have to get the csv and turn it back into json.

You have to do a release every time you want to change translations. Most our sites using these translations are simple static sites running on s3. However it takes developer time and effort that could be better spent doing something else.

In wanting to improve this system I decided to use firebase's realtime database to store and edit our translations instead. I created a frontend for it that makes it easy for other employees who may know the language but not the code to make edits to the language for us It saves developer time not having to manage translations and releases for them. Changes show up instantly on the site.

The structure of the data in firebase looks something like this

{
  "dev":{
    "site1":{
      "en-US":{
        "key":"value"
      }
    }
  },
  "live":{}
}

Now we have storage by evironment/application/language The reason to have different enviroments was so if you made a stupid mistake like deleting an entire language you could back it up from live again. I also added some rules to firebase to allow only certain people to update the live keys.

Looks something like this

{
  "rules": {
    ".read": "true",
      "dev":{
        ".write": "auth != null"
      },
	    "live":{
        ".write": "auth.permissions.writeToLive === true"
      }
  }
}

This allows anyone to read (which is what want) but only certain people to edit live. These permission come from using custom auth with firebase. (I'll write up on how to do that tomorrow!)

I won't go into much detail about how to get items from firebase becasue it is very well documented on their site and elsewhere. However I will say it's very easy to get whatever language you want with a simple ref

//Add some code to conditionally set your env.
var env = "dev"
var app = "some app" //This could be hard-coded]
var language = "en-US" //Also have code to set your language
// I use `once` here because I don't want the overhead of querying firebase for changes all the time
// When we really dont need it.
return firebase.database().ref(`${env}/${app}/${language}).once("value").then((snap)=>{
 //All your data is here
 return snap.val();
});

We use angular for several of our apps. If you also use the angular translate library it's easy to get setup using a custom loader

Config

//...
.config(function($stateProvider, $urlRouterProvider, $translateProvider) {
    $urlRouterProvider.otherwise('/home');
    $translateProvider.useLocalStorage();
    $translateProvider.useSanitizeValueStrategy();
    $translateProvider.useLoader("Translate")
//...

Factory

//...
.factory("Translate", function(){
var env;
var app;
//Fill in these values yourself!
var config = {
    apiKey: "",
    authDomain: "",
    databaseURL: "",
    storageBucket:""
    messagingSenderId: ""
  };
  firebase.initializeApp(config);
  if(window.env === "prod"){
    env = "live";
  }
  return function(options){
    var key;
    //Angular translate is stupid and uses `_` where we want `-`
    var parts = options.key.split("_");
    key = parts[0] + "-" + parts[1].toUpperCase();
    return e.database().ref(`${env}/${app}/${key}`).once("value").then((snap)=>{
      return snap.val()
    });
  }
})

have fun.