2

I would like to shorten "NSLocalizedString" to "_" so I'm using macro _(x) NSLocalizedString(@x, @__FILE__) .

But now, when I want to generate strings for localization with find . -name \*.m | xargs genstrings it generates nothing.

Any help?

user500
  • 4,519
  • 6
  • 43
  • 56

4 Answers4

4

You can tell genstrings to look for a different function by using the '-s' argument:

genstring -s MyFunctionName ....

However, MyFunctionName must follow the same naming and argument conventions as one of the built in NSLocalizeString macros.

In your case, you can not just specify the string key, you must also specify the documentation string. In fact, you should never generate a strings file without both the string and documentation. There are many languages where the actual phrase or word will depend on context. German is a great example where a car is "das auto" and more than one is "die autos". There are many more examples that include changes for gender, number, time, question versus statement, and yes versus no. The documentation string helps your translator figure out what translation to use.

In addition, the best practice is to use a key that is different from the native language word. That says use NSLocalizedStringWithDefaultValue(key, table, bundle, val, comment). You can specify nil for the table and [NSBundle mainBundle] for the bundle argument.

You can wrap this in a shorthand, but you still have to follow the StringWithDefaultValue name and the arguments for genstrings to work.

I strongly recommend you look at the WWDC 2012 session on Localization Tips and Tricks.

Maurice

  • That's really lame that we can't pass default values in for things (such as bundle) and use a short-hand macro with genstrings – jmstone617 Mar 08 '13 at 16:15
3

You can use the -s option of genstrings. From the man page :

-s routine
Substitutes routine for NSLocalizedString. For example, -s MyLocalString will catch calls to MyLocalString and MyLocalStringFromTable.

So I think you could try :

genstrings -s _

  • Got: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFString characterAtIndex:]: Range or index out of bounds' – user500 Jan 20 '12 at 13:27
  • That's unlikely to work because _ will appear in loads of places in your code that aren't NSLocalizedString calls. You'll have to pick a more unique macro name, such as _LS. It also may not work if your macro doesn't take two arguments like the standard NSLocalizedString function does, but you'd have to try it yourself. – Nick Lockwood Jan 20 '12 at 14:38
2

I had the same problem when my NSLocalizedString macro was taking 1 argument instead of 2 like genstrings expects, so i wrote i python script that does the job.

the first argument for the script is the macro name and the second is the path to your project.

import fnmatch
import os
from xml.dom import minidom

function = sys.argv[1]
rootdir  = sys.argv[2]

# Generate strings from .m files

files = []
for root, dirnames, filenames in os.walk(rootdir):
  for filename in fnmatch.filter(filenames, '*.m'):
      files.append(os.path.join(root, filename))

strings = []
for file in files:
    lineNumber = 0
    for line in open(file):
        lineNumber += 1
        index = line.find(function)
        if (index != -1):
            callStr = line[index:]
            index = callStr.find('@')
            if (index == -1):
                print 'call with a variable/macro. file: ' + file + ' line: %d' % lineNumber
            else:
                callStr = callStr[index+1:]
                index = callStr.find('")')
                callStr = callStr[:index+1]
                if callStr not in strings:
                    strings.append(callStr) 

# Write strings to file

f = open('Localizable.strings', 'w+')           
for string in strings:
    f.write(string + ' = ' + string + ';\n\n')
f.close()
Or Arbel
  • 2,965
  • 2
  • 30
  • 40
0

I have improved Or Arbel's script to include the cases where there's multiple macro-calls on a single line:

import fnmatch
import os
from xml.dom import minidom
import sys

function = sys.argv[1]
rootdir  = sys.argv[2]

# Generate strings from .m files

files = []
for root, dirnames, filenames in os.walk(rootdir):
  for filename in fnmatch.filter(filenames, '*.m'):
      files.append(os.path.join(root, filename))

strings = []
for file in files:
    lineNumber = 0
    for line in open(file):
        lineNumber += 1

        index = line.find(function)
        startIndex = 0
        while (index != -1):

            startIndex = index+1

            callStr = line[index:]
            index = callStr.find('@')
            if (index == -1):
                print 'call with a variable/macro. file: ' + file + ' line: %d' % lineNumber
            else:
                callStr = callStr[index+1:]
                index = callStr.find('")')
                callStr = callStr[:index+1]
                if callStr not in strings:
                    strings.append(callStr)

            index = line.find(function, startIndex)


# Write strings to file

f = open('Localizable.strings', 'w+')           
for string in strings:
    f.write(string + ' = ' + string + ';\n\n')
f.close()
ullstrm
  • 9,812
  • 7
  • 52
  • 83