Skip to content

Instantly share code, notes, and snippets.

@fxthomas
Created May 7, 2012 10:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fxthomas/2627133 to your computer and use it in GitHub Desktop.
Save fxthomas/2627133 to your computer and use it in GitHub Desktop.
iLocalize -- Xcode project localizer
#!/usr/bin/python
# coding=utf-8
# Base Python File (ilocalize.py)
# Created: Sun May 6 11:18:15 2012
# Version: 1.0
#
# This Python script was developped by François-Xavier Thomas.
# You are free to copy, adapt or modify it.
# If you do so, however, leave my name somewhere in the credits, I'd appreciate it ;)
#
# (ɔ) François-Xavier Thomas <fx.thomas@gmail.com>
import os
import argparse
import re
import collections
from subprocess import call
#################
# Parse options #
#################
parser = argparse.ArgumentParser(formatter_class = argparse.RawDescriptionHelpFormatter,
description="""Extracts relevant strings from XIB and Storyboard files.
Usage examples:
* Create localized files from XIB/Storyboards:
ilocalize -s ./Localized/ -d en -l en,fr,ca .
* Translate them
* Update the XIB/Storyboards:
ilocalize -s ./Localized/ -d en -l en,fr-ca -w .""")
parser.add_argument ('-s', '--strings-dir', action='store', dest='strings_dir', help='Output directory for .strings files (default: ./Localized)', default="./Localized/")
parser.add_argument ('-d', '--default-language', action='store', dest='default_language', help='Default language for non-localized files (default: en)', default="en")
parser.add_argument ('-l', '--languages', action='store', dest='languages', help='Languages to generate (default: auto)', default="auto")
parser.add_argument ('-w', '--write', action='store_true', dest='write', help='Write contents of the input directory into storyboard/XIB files', default=False)
parser.add_argument ('input', help='Input directory (default: ./)', default=['./'], nargs='*')
namespace = parser.parse_args()
##############
# Initialize #
##############
lproj_re = re.compile (r'.*\/(?P<language>[a-zA-Z_]+)\.lproj\/(?P<filename>[^/]*)$')
files = collections.defaultdict(dict)
filenamelist = {}
languages = set()
# Append filename to collection
def _append (filename):
match = lproj_re.match(filename)
language = namespace.default_language
fn = os.path.basename(filename)
if match is not None:
language = match.group('language')
files[language][fn] = filename
if language == namespace.default_language:
filenamelist[fn] = filename
#####################
# Prepare languages #
#####################
if namespace.languages != "auto":
languages = namespace.languages.split(",")
for l in languages:
files[l] = {}
#####################
# Prepare file list #
#####################
print ("Preparing file list...")
for f in namespace.input:
if os.path.isdir(f):
for dirpath,_,filenames in os.walk (f, followlinks=True):
for ff in filenames:
_,ext = os.path.splitext (ff)
if ext == ".storyboard" or ext == ".xib":
_append (os.path.join (dirpath, ff))
else:
_,ext = os.path.splitext (f)
if ext == ".storyboard" or ext == ".xib":
_append (os.path.join (dirpath, f))
#############################
# Create output directories #
#############################
if not namespace.write:
# Create output dir if it doesn't exist
print ("Creating output directories...")
if not os.path.exists(namespace.strings_dir):
print (" " + namespace.strings_dir)
os.mkdir (namespace.strings_dir)
# Create language dirs if they don't exist
for l in files:
d = os.path.join (namespace.strings_dir, "{0}.lproj".format(l))
print (" " + d)
if not os.path.exists(d):
os.mkdir (d)
# And loop through each file
for language, filelist in files.items():
print ("Processing language '{0}'".format(language))
outf = os.path.join (namespace.strings_dir, "{0}.lproj".format(language))
##########################
# Process existing files #
##########################
for fn,fullf in filelist.items():
print " {0}".format(fn)
if namespace.write:
call (["ibtool",
"--strings-file", os.path.join (outf, "{0}.strings".format(fn)),
"--write", fullf,
fullf])
else:
call (["ibtool",
"--generate-strings-file", os.path.join (outf, "{0}.strings".format(fn)),
fullf])
###########################################
# Prepare defaults for non-existing files #
###########################################
for fn in [fn for fn in filenamelist if not fn in files[language]]:
if namespace.write:
write_to = filenamelist[fn]
p = os.path.dirname (write_to)
f = os.path.basename (write_to)
if ".lproj" in p:
p = re.sub (r'\/[a-zA-Z_]+\.lproj', r'/{0}.lproj'.format(language), p)
else:
p = os.path.join (p, "{0}.lproj".format(language))
if not os.path.exists(p):
os.mkdir(p)
write_to = os.path.join (p, f)
print " {0} -> {1}".format(fn, write_to)
call (["ibtool",
"--strings-file", os.path.join (outf, "{0}.strings".format(fn)),
"--write", write_to,
filenamelist[fn]])
else:
print " {0}".format(fn)
call (["ibtool",
"--generate-strings-file", os.path.join (outf, "{0}.strings".format(fn)),
filenamelist[fn]])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment