11 Nov

Nocturnarya: localized versions

Our current project is the localization of Nocturnarya Collector’s Edition. As usual, our target languages are: German, French, Dutch, Spanish, Portuguese and Italian. It’ll be a Windows-only release. This localization is a daunting task, which comprises a few intricate parts:

  • The Story: Nocturnarya’s story is a bit long, as the game builds a particular vampire lore, with adventure, scheming, military invaders, treasons and loyalty. The game portrays several characters of which the most important is you, the player. At its core, it’s a battle between you and Grysmore, the boss of the human invaders.
  • The vampire and the vampiress: In the original English game, you can choose how you want to be referred to as the story progresses: as a vampire, a vampiress, or a rockstar renegade. Localizing this is tricky, because of articles and genre-specific details in all the target languages. We’ll be removing the rockstar renegade option, and will do our best to keep the vampire and vampiress options. However, if it proves to be too error-prone we’ll just scrap this option altogether.
  • The Village: The game has a section that allows you to build a 3D village for your vampire tribe. However, the help window and the tutorials amount to a lot of text to translate.
  • The Match 3 levels: This includes all the help texts, instructions and user interface of the Match 3 levels.
  • Collector’s Edition goodies: Last but not least, we’ll have to translate the extra stories and minigames offered as Collector’s Edition exclusive bonuses.

If everything goes smoothly, this localization should be completed by the end of this month.

Nocturnarya Sammleredition
Nocturnarya Sammleredition
31 Aug

Extracting text from PSD files

Typically, we need to translate hundreds of strings when localizing our games. Most strings are text messages which the game loads from some database or simple text file. However, we often have to handle localization of several PNG images, such as the one below.

AWESOME! message in DragonScales

Such PNG images are exported from PSD files which must obviously contain at least one Text Layer. To speed up the localization process we have a little Photoshop script which opens the PSD files and extracts all the text we have to translate. PSD files are grouped in directories corresponding to the tileset they belong to. For instance, this would be a typical directory structure for the DragonScales games:

images/
    board/
        awesome.psd, great.psd, ...
    cards
        youwin.psd, sorry.psd, ...
    ending
        congratulations.psd, ...
    levelselect
        clickhere.psd, ...
    mainmenu
        welcome.psd, ...
    etc

A simplified but functional version of the script we use is this:

#target photoshop

var target = "/C/projects/ds/images";
var toLocalize = new Array();
var totalProcessed = 0;
var warningsFiles = new Array();

function log(msg) {
	$.writeln(msg);
}

function processPSDFolder(dir) {
	var files = dir.getFiles("*.psd");
    log("===============================================");
    log(dir + " -> "+ files.length);
    log("===============================================");
	for (var i = 0; i < files.length; i++) {
    	var doc = app.open(files[i]);
    	log("  file: " + files[i]);
        totalProcessed++;
        if ( doc.artLayers.length == 0 ) {
            log("   -> WARNING: ZERO TEXT LAYERS? THEY SHOULD NOT BE IN GROUPS.");
            warningsFiles.push(files[i]);
        }
    	for (var j = 0; j < doc.artLayers.length; j++) {
        	var lyr = doc.artLayers[j];
        	if (lyr.kind == LayerKind.TEXT) {
            	var lyr = doc.artLayers[j];
            	log("   ->" + lyr.textItem.contents);
            	toLocalize.push(lyr.textItem.contents);
        	}
     	}
    	doc.close(SaveOptions.DONOTSAVECHANGES);
	}
}

function saveStrings() {
	var out = new File(target + "/strings.txt");
	out.open("w");
	for (var i = 0; i < toLocalize.length; i++) {
		var str = toLocalize[i];
		out.writeln(str);
	}
 	out.close();
}

var root = Folder(target).getFiles();
for ( var i = 0; i < root.length; i++ ) {
	var fileFoldObj = root[i];
	if ( fileFoldObj instanceof File ) {         
        // Discard files at this level
	} else {
         processPSDFolder( Folder(fileFoldObj) );
	}
}
saveStrings();
log("Total PSDs processed: " + totalProcessed);
log("Warnings: " + warningsFiles.length);
for ( var i = 0; i < warningsFiles.length; i++ ) {
	log(" " + warningsFiles[i]);
}

Observations:

  • target is the path to your directory structure holding the PSD files.
  • The strings to be translated will we written to file strings.txt under your target directory.
  • This script looks for text layers on the top level of the PSD. It can be easily extended to inspect layers in groups, though.
  • We use warnings to be notified about files not containing Text Layers. These might be files requiring special exporting and extra formatting, and therefore we’ll have to handle such files exceptionally.