diff --git a/xwords4/android/XWords4/res_src/values-ca/strings.xml b/xwords4/android/XWords4/res_src/values-ca/strings.xml index 59b569b21..702511e58 100644 --- a/xwords4/android/XWords4/res_src/values-ca/strings.xml +++ b/xwords4/android/XWords4/res_src/values-ca/strings.xml @@ -324,7 +324,7 @@ " vs. " - %1$d fitxes romanents al sac. + Queden %1$d fitxes al sac. @@ -672,9 +672,9 @@ Copia al porta-retalls Suprimeix la selecció - S\'han copiat %1$d paraules - - + S\'han copiat %1$d paraules + + S\'ha afegit %1$s a la llista d\'estudi %2$s Llista d\'estudi per a %1$s @@ -808,9 +808,9 @@ Oponent - %1$s ha jugat %2$s i anota %3$d punts - - + %1$s ha jugat %2$s i anota %3$d punts + + %1$s ha canviat %2$d fitxes @@ -893,7 +893,7 @@ La versió del Crosswords al telèfon amb número «%1$s» no és compatible amb aquest per a jugar via SMS. Heu d\'actualitzar abans de continuar. - Selecioneu fins a %1$d aparells que voleu incloure en aquesta partida. Useu el botó «%2$s» si no veieu l\'aparell que espereu. + Seleccioneu fins a %1$d aparells que voleu incloure en aquesta partida. Useu el botó «%2$s» si no veieu l\'aparell que espereu. @@ -1043,4 +1043,6 @@ Gestió de les invitacions per a tornar a jugar la partida. Us mostrarem aquest missatge mentre no l\'accepteu.\n\nNo heu de tenir aquesta partida oberta mentre espereu. Rebreu una notificació quan la partida estigui preparada per a jugar. Convida l\'amfitrió redirigit - + No puc trobar cap jugada + + diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java index 9fdc0e99d..268451827 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictsDelegate.java @@ -1140,50 +1140,53 @@ public class DictsDelegate extends ListDelegateBase JSONObject theOne = null; String langName = null; String json = NetUtils.runPost( post, new JSONObject() ); - try { - JSONObject obj = new JSONObject( json ); - JSONArray langs = obj.optJSONArray( "langs" ); - int nLangs = langs.length(); - for ( int ii = 0; ii < nLangs; ++ii ) { - JSONObject langObj = langs.getJSONObject( ii ); - String langCode = langObj.getString( "lc" ); - if ( ! langCode.equals( m_lc ) ) { - continue; - } - // we have our language; look for one marked default; - // otherwise take the largest. - m_langName = langObj.getString( "lang" ); - JSONArray dicts = langObj.getJSONArray( "dicts" ); - int nDicts = dicts.length(); - int theOneNWords = 0; - for ( int jj = 0; jj < nDicts; ++jj ) { - JSONObject dict = dicts.getJSONObject( jj ); - if ( dict.optBoolean( "isDflt", false ) ) { - theOne = dict; - break; - } else { - int nWords = dict.getInt( "nWords" ); - if ( null == theOne || nWords > theOneNWords ) { + if ( null != json ) { + try { + JSONObject obj = new JSONObject( json ); + JSONArray langs = obj.optJSONArray( "langs" ); + int nLangs = langs.length(); + for ( int ii = 0; ii < nLangs; ++ii ) { + JSONObject langObj = langs.getJSONObject( ii ); + String langCode = langObj.getString( "lc" ); + if ( ! langCode.equals( m_lc ) ) { + continue; + } + // we have our language; look for one marked default; + // otherwise take the largest. + m_langName = langObj.getString( "lang" ); + JSONArray dicts = langObj.getJSONArray( "dicts" ); + int nDicts = dicts.length(); + int theOneNWords = 0; + for ( int jj = 0; jj < nDicts; ++jj ) { + JSONObject dict = dicts.getJSONObject( jj ); + if ( dict.optBoolean( "isDflt", false ) ) { theOne = dict; - theOneNWords = nWords; + break; + } else { + int nWords = dict.getInt( "nWords" ); + if ( null == theOne + || nWords > theOneNWords ) { + theOne = dict; + theOneNWords = nWords; + } } } } - } - // If we got here and theOne isn't set, there is - // no wordlist available for this language. Set - // the flag so we don't try again, even though - // we've failed. - if ( null == theOne ) { - XWPrefs.setPrefsBoolean( m_context, - R.string.key_got_langdict, - true ); - } + // If we got here and theOne isn't set, there is + // no wordlist available for this language. Set + // the flag so we don't try again, even though + // we've failed. + if ( null == theOne ) { + XWPrefs.setPrefsBoolean( m_context, + R.string.key_got_langdict, + true ); + } - } catch ( JSONException ex ) { - DbgUtils.loge( ex ); - theOne = null; + } catch ( JSONException ex ) { + DbgUtils.loge( ex ); + theOne = null; + } } if ( null != theOne ) { diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetUtils.java index 71624ed0b..39dae2b86 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/NetUtils.java @@ -244,6 +244,8 @@ public class NetUtils { } } catch( java.io.UnsupportedEncodingException uee ) { DbgUtils.loge( uee ); + } catch( java.net.UnknownHostException uhe ) { + DbgUtils.loge( uhe ); } catch( java.io.IOException ioe ) { DbgUtils.loge( ioe ); } diff --git a/xwords4/android/scripts/fix_loc_xmls.py b/xwords4/android/scripts/fix-loc-xmls.py similarity index 52% rename from xwords4/android/scripts/fix_loc_xmls.py rename to xwords4/android/scripts/fix-loc-xmls.py index 814d5ab2d..4a5f9f944 100755 --- a/xwords4/android/scripts/fix_loc_xmls.py +++ b/xwords4/android/scripts/fix-loc-xmls.py @@ -4,13 +4,31 @@ import mk_xml, os, sys, getopt, re from lxml import etree +g_verbose = False + +def getDocNames( doc ): + stringNames = {} + pluralsNames = {} + + for elem in doc.getroot(): + if elem.tag == 'string': stringNames[elem.get('name')] = True + elif elem.tag == 'plurals': pluralsNames[elem.get('name')] = True + + return { 'stringNames' : stringNames, + 'pluralsNames' : pluralsNames, + } + +def getEnglishNames(): + doc = etree.parse("res/values/strings.xml") + return getDocNames( doc ) + def longestCommon( name, pairs ): match = None for ii in range(1, len(name)): str = name[:ii] for key in pairs.keys(): if str == key[:ii]: - print str, "matches", key, "so far" + if g_verbose: print str, "matches", key, "so far" match = key break return match @@ -50,28 +68,40 @@ def checkAgainst( doc, pairs ): # response = raw_input( "unknown name: %s; respond:" % (name) ) # print "you wrote:", response -def findWithName( doc, name ): +def findWithName( doc, name, tag ): result = None - for string in doc.findall('string'): + for string in doc.findall(tag): if string.get('name') == name: result = string break - print 'findWithName=>', result, 'for', name + # if g_verbose: print 'findWithName=>', result, 'for', name return result +def makePluralsFrom( src ): + newNode = etree.fromstring('' % (src.get('name'))) + for item in src.findall('item'): + obj = etree.fromstring('XLATE ME: %s' + % (item.get('quantity'), item.text)) + newNode.append(obj) + return newNode + def insertAfter( locRoot, englishElem, lastMatch, prevComments ): name = englishElem.get('name') text = englishElem.text - print "insertAfter(", locRoot, englishElem.get('name'), lastMatch.get('name'), prevComments, ")" + if g_verbose: print "insertAfter(", locRoot, englishElem.get('name'), lastMatch.get('name'), prevComments, ")" index = locRoot.getchildren().index(lastMatch) - print 'index:', index + if g_verbose: print 'index:', index for comment in prevComments: commentNode = etree.Comment(comment) index += 1 locRoot.insert( index, commentNode ) - newNode = etree.fromstring('XLATE ME: %s' % (name, text)) + if 'string' == englishElem.tag: + newNode = etree.fromstring('XLATE ME: %s' % (name, text)) + elif 'plurals' == englishElem.tag: + newNode = makePluralsFrom(englishElem) + else: sys.exit(1) index += 1 locRoot.insert( index, newNode ) @@ -80,6 +110,14 @@ def longFormFor(fmt ): elif fmt == '%d': return '%1$d' else: assert False +def printStats( doc ): + engNames = getEnglishNames() + langNames = getDocNames( doc ) + print "strings: English: %d; lang: %d" % (len(engNames['stringNames']), + len(langNames['stringNames'])) + print "plurals: English: %d; lang: %d" % (len(engNames['pluralsNames']), + len(langNames['pluralsNames'])) + def replacePcts( doc ): pat = re.compile( '(%[sd])', re.DOTALL | re.MULTILINE ) for string in doc.findall('string'): @@ -95,29 +133,29 @@ def replacePcts( doc ): # elem before it that is in doc and insert it after. Start over each # time to avoid problems with iteration and order def doAddMissing( doc ): - done = False - while not done: - locRoot = doc.getroot() - lastMatch = None - prevComments = [] - for elem in etree.parse("res/values/strings.xml").getroot().iter(): - if not isinstance( elem.tag, basestring ): - prevComments.append( elem.text ) - print "added comment:", elem.text - elif 'string' == elem.tag: - name = elem.get('name') - match = findWithName( locRoot, name ) - print 'elem', name, 'has comments', prevComments - if None == match: - print 'NO match for', name - insertAfter( locRoot, elem, lastMatch, prevComments ) - done = True - # sys.exit(0) - else: - print 'got match for', name - lastMatch = match - lastComments = prevComments - prevComments = [] + locRoot = doc.getroot() + lastMatch = None + prevComments = [] + resources = etree.parse("res/values/strings.xml").getroot() + for elem in resources: + # if g_verbose: print "got elem:", elem + tag = elem.tag + if not isinstance( tag, basestring ): + prevComments.append( elem.text ) + # if g_verbose: print "added comment:", elem.text + elif 'string' == tag or 'plurals' == tag: + name = elem.get('name') + match = findWithName( locRoot, name, tag ) + if None == match: + if g_verbose: print 'NO match for', name + insertAfter( locRoot, elem, lastMatch, prevComments ) + else: + lastMatch = match + lastComments = prevComments + prevComments = [] + else: + print "unexpected tag:", elem.tag + sys.exit(1) def compare( engPairs, docPath ): locStrings = mk_xml.getStrings( docPath, True ) @@ -127,29 +165,67 @@ def compare( engPairs, docPath ): otherOnly = [key for key in locStrings.keys() if not key in engPairs] print "%d strings missing from English: %s" % (len(otherOnly), ", ".join(otherOnly)) +def removeNotInEnglish( doc ): + locRoot = doc.getroot() + engNames = getEnglishNames() + for elem in locRoot: + if not isinstance( elem.tag, basestring ): + prevComment = elem + elif elem.tag == 'string': + name = elem.get('name') + if not name in engNames['stringNames']: + print "removing string", name + locRoot.remove(elem) + if prevComment: locRoot.remove(prevComment) + prevComment = None + elif elem.tag == 'plurals': + name = elem.get('name') + if not name in engNames['pluralsNames']: + print "removing plurals", name + locRoot.remove(elem) + if prevComment: locRoot.remove(prevComment) + prevComment = None + else: + print "unknown tag", elem.tag + sys.exit(1) + + def usage(): print "usage:", sys.argv[0] print " -a # insert missing string elements for translation" print " -c # compare each file with the English, listing string not in both" + print " -i # save any changes made (does not by default)" print " -f # work on this strings.xml file (does all if none specified)" + print " -l # work on the strings.xml file for this language (e.g. ca, nl)" + print " -r # remove elements not present in English" + print " -s # print stats" print " -% # replace %[sd] with the correct longer form" - print " -s # save any changes made (does not by default)" sys.exit(1) +def langFileFor(code): + return "res_src/values-%s/strings.xml" % code + def main(): + global g_verbose stringsFiles = [] addMissing = False doSave = False doCompare = False doReplace = False + doRemove = False + doStats = False try: - pairs, rest = getopt.getopt(sys.argv[1:], "acf:s%") + pairs, rest = getopt.getopt(sys.argv[1:], "acf:il:rsv%") for option, value in pairs: if option == '-a': addMissing = True elif option == '-c': doCompare = True - elif option == '-%': doReplace = True + elif option == '-i': doSave = True elif option == '-f': stringsFiles.append(value) - elif option == '-s': doSave = True + elif option == '-l': stringsFiles.append(langFileFor(value)) + elif option == '-v': g_verbose = True + elif option == '-r': doRemove = True + elif option == '-s': doStats = True + elif option == '-%': doReplace = True else: usage() except: usage() @@ -164,11 +240,20 @@ def main(): parser = etree.XMLParser(remove_blank_text=True, encoding="utf-8") for path in stringsFiles: + print "looking at", path doc = etree.parse(path, parser) # checkAgainst( doc, pairs ) - if doReplace: replacePcts( doc ) - if addMissing: doAddMissing( doc ) - if doCompare: compare( pairs, path ) + if doReplace: + replacePcts( doc ) + if addMissing: + doAddMissing( doc ) + if doCompare: + compare( pairs, path ) + if doRemove: + removeNotInEnglish( doc ) + # print stats after any other changes have been made + if doStats: + printStats( doc ) if doSave: out = open( path, "w" ) out.write( etree.tostring( doc, pretty_print=True, encoding="utf-8", xml_declaration=True ) )