You can use profile documents for this use case as the content gets changed only with new versions of your project probably. So, you can easily live with profile document's caching.
You get the label translation from a profile document with
var doc = database.getProfileDocument("LabelsEnglish", "");
var label = doc.getItemValueString("label1");
doc.recycle();
return label;
You could read all labels in an application scope variable Map too and do your own caching. This way profile documents would get read only once.
if (!applicationScope.labels) {
var map = new java.util.HashMap();
var doc = database.getProfileDocument("LabelsEnglish", "");
var allItems = doc.getItems();
for (var i = 0; i < allItems.size(); i++) {
var item = allItems.elementAt(i);
item.getName();
map.put(item.getName(), item.getValueString());
item.recycle();
}
doc.recycle();
applicationScope.labels = map;
}
Execute the SSJS code above in a custom control which is included in every XPage (e.g. application layout custom control) in before page load event so you can be sure application scope variable "labels" is initialized when you want to use it. You can access the labels easily with EL
applicationScope.labels.label1