Module egg_translations
[hide private]

Source Code for Module egg_translations

   1  #!/bin/env python 
   2  # -*- coding: utf-8 -*- 
   3   
   4  #   Copyright (c) 2006-2009 Open Source Applications Foundation 
   5  # 
   6  #   Licensed under the Apache License, Version 2.0 (the "License"); 
   7  #   you may not use this file except in compliance with the License. 
   8  #   You may obtain a copy of the License at 
   9  # 
  10  #       http://www.apache.org/licenses/LICENSE-2.0 
  11  # 
  12  #   Unless required by applicable law or agreed to in writing, software 
  13  #   distributed under the License is distributed on an "AS IS" BASIS, 
  14  #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  15  #   See the License for the specific language governing permissions and 
  16  #   limitations under the License. 
  17   
  18  """ 
  19  Egg Translations Management Package 
  20   
  21  @author: Brian Kirsch - bkirsch@osafoundation.org 
  22  @author: Markku Mielityinen - mmmm@osafoundation.org 
  23  @contact: Grant Baillie - grant@osafoundation.org 
  24  @copyright: Copyright (c) 2006-2009 Open Source Applications Foundation 
  25  @license:   Apache License, Version 2.0 
  26  """ 
  27   
  28  __all__ = ["DefaultTranslations", "EggTranslations", "hasCountryCode", 
  29             "stripCountryCode", "stripEncodingCode", "logger"] 
  30   
  31  import pkg_resources 
  32  from cStringIO import StringIO 
  33  import types 
  34  import sys 
  35  from gettext import GNUTranslations 
  36  import logging 
  37   
  38  logger = logging.getLogger(__name__) 
  39   
40 -class INIParsingException(Exception):
41 pass
42
43 -class DefaultTranslations(GNUTranslations):
44 - def ugettext(self, message, *args):
45 """ 46 Extends C{GNUTranslations} ugettext 47 method adding the ability to pass 48 a default argument which will be 49 returned if no localization is 50 found for the message key. 51 52 @param message: C{unicode} or {str} message key 53 used to lookup a localization 54 55 @type message: C{unicode} or ASCII {str} 56 57 @param args: An optional argument which if passed 58 will be returned if no localzation 59 found for message. The type of the 60 return value in the args list 61 has no limitations. 62 63 @type args: C{list} 64 65 @return: C{unicode} localized message or 66 either the original message argument 67 or the default value in args if no 68 localization found. 69 70 """ 71 72 if not args: 73 return GNUTranslations.ugettext(self, message) 74 75 missing = object() 76 tmsg = self._catalog.get(message, missing) 77 78 if tmsg is missing: 79 if self._fallback: 80 return self._fallback.ugettext(message, args[0]) 81 82 # return the default value not the message value 83 # as GNUTranslations does. 84 return args[0] 85 86 return tmsg
87 88 """ 89 TO DO: 90 ================= 91 1. Overwrite of a key ie domain, name, locale 92 should print a warning. 93 94 2. Only one definition of a locale in a 95 resource file per project can't have 96 [myproject::fr_CA, fr] then later [myproject::fr]. 97 Need to error or print warning. 98 99 3. Clean up debug logging messages to be less 100 verbose and more useful. 101 102 4. Make sure at least one locale passed in 103 locale set. 104 """ 105
106 -class EggTranslations(object):
107 108 __slots__ = ["_init", "_iniFileName", "_localeSet", "_fallback", 109 "_iniCache", "_gtCache", "_moCache", "_localeCache", 110 "_iniEncoding"] 111 112 _NAME = "EggTranslations" 113
114 - def __init__(self):
115 super(EggTranslations, self).__init__() 116 117 # Flag indicating whether the initialize method 118 # has been called 119 self._init = False 120 121 self._iniFileName = None 122 self._iniEncoding = None 123 124 self._localeSet = None 125 self._fallback = False 126 127 # Cache for key values pairs in ini file. 128 # Persists for the life of the EggTranslations 129 # instance. 130 self._iniCache = {} 131 132 # Cache for the file path to gettext .mo localizations. 133 # Persists for the life of the EggTranslations 134 # instance. 135 self._moCache = {} 136 137 # Holds the EggTranslations for locale set. 138 # Is flushed when the locale set changes. 139 self._gtCache = {} 140 141 # Cache each locale that has an ini definition 142 # for a project. The definition can be any key 143 # value pair and is not required to be a gettext 144 # mo file. 145 # Persists for the life of the EggTranslations 146 # instance. 147 self._localeCache = {}
148 149 150
151 - def initialize(self, localeSet, iniFileName="resources.ini", 152 encoding="UTF-8", fallback=True):
153 """ 154 The initialize method performs the following operations: 155 156 1. Calls the C{pkg_resources.add_activation_listener} 157 method passing the L{EggTranslations._parseINIFiles} 158 method as the callback. See the parseINIFiles method 159 for more info on loading resources and 160 gettext translation files. 161 162 163 2. Calls the EggTranslations setLocaleSet method 164 passing the localeSet param. See the setLocaleSet 165 method documentation for more info. 166 167 The initialize method sets the locale set and loads the 168 resource and translation caches. 169 170 It must be called before using the EggTranslations API. 171 172 The initialize method can only be called once per 173 EggTranslations instance. 174 175 @raise INIParsingException: 176 @raise LookupError: 177 @raise UnicodeDecodeError: 178 @raise UnicodeEncodeError: 179 180 @param localeSet: A C{unicode} or C{str} or C{list} 181 containing locale country and language 182 codes. The value(s) must be able to 183 be converted to ASCII. 184 185 @type localeSet: ASCII C{str} or C{unicode} or 186 C{list} containing ASCII 187 C{str} or C{unicode} values 188 189 @param iniFileName: The name of the resource ini file 190 in the egg's info directory. 191 192 This file contains the location of 193 localized and non-localized resources 194 as well as translation files in gettext 195 mo format. The default value for this 196 file is "resources.ini". If a C{str} 197 is passed it must be able to be 198 converted to C{unicode} using the 199 encoding passed to the initialize 200 method. The default encoding 201 is "UTF-8". 202 203 @type iniFileName: ASCII C{str} or C{unicode} 204 205 @param encoding: The character set encoding of the 206 iniFileName. This encoding will be 207 used to convert C{str} values contained 208 in the iniFileName to C{unicode}. 209 The default encoding is "UTF-8". 210 211 @type encoding: ASCII C{str} or C{unicode} 212 213 @param fallback: Indicates whether locale set fallback should 214 take place. If set to True, the 215 EggTranslations will search all locales 216 in the locale set till a resource or 217 gettext mo translation file is found. If 218 set to False the EggTranslations will 219 only try to locate a resource or 220 gettext mo translation file for the 221 current locale which is the first locale 222 in the locale set. 223 224 225 @type fallback: C{boolean} 226 227 """ 228 assert(self._init, False, 229 "EggTranslations already initialized") 230 231 if type(iniFileName) == types.StringType: 232 iniFileName = unicode(iniFileName, 233 sys.getfilesystemencoding()) 234 235 if type(encoding) == types.StringType: 236 # If encoding is a str it should only have 237 # ASCII characters 238 encoding = unicode(encoding) 239 240 assert(type(iniFileName) == types.UnicodeType) 241 assert(type(encoding) == types.UnicodeType) 242 assert(type(fallback) == types.BooleanType) 243 244 self._init = True 245 self._fallback = fallback 246 247 self._iniFileName = iniFileName 248 self._iniEncoding = encoding 249 250 pkg_resources.add_activation_listener(self._parseINIFiles) 251 self.setLocaleSet(localeSet, fallback)
252
253 - def hasKey(self, project, name, locale=None):
254 """ 255 returns True if a key was specified in one or more 256 eggs resource ini files (default is "resource.ini") 257 for the given project and name. 258 259 The locale is an optional argument. By default 260 the locale set is searched in fallback order as well 261 as the 'all' default locale (if fallback=True in the 262 initialize or setLocaleSet method) until a 263 key is found. If no key found the method returns False. 264 265 However, if a locale is specified the method will only 266 search for a key in the resource ini files for the 267 given locale. 268 269 270 @raise UnicodeDecodeError: 271 @raise UnicodeEncodeError: 272 273 @param project: A project is a root namespace under which 274 resources and localizations exist. 275 276 A project name matches an egg name. 277 An egg's info file can contain resource 278 and localizations for more than one project. 279 280 The project name must be either an ASCII 281 C{str} or C{unicode}. 282 283 @type project: ASCII C{str} or C{unicode} 284 285 @param name: name is the key to lookup in 286 a resource ini file to retrieve the 287 value specifed. For example, 288 myname = this is my value. 289 290 The name must be either an ASCII 291 C{str} or C{unicode}. 292 293 @type name: ASCII C{str} or C{unicode} 294 295 296 @param locale: Optional argument that if specified 297 tells the method to only return True 298 if key is present in one or more 299 ini files for the given locale. 300 This parameter if specified must contain 301 a valid language / country locale 302 i.e. "en_US" or "en" 303 304 @type locale: C{unicode} or ASCII C{str} 305 306 @return: C{bool} True if the name is found otherwise False 307 """ 308 309 assert(self._init, True) 310 311 if type(project) == types.StringType: 312 project = unicode(project) 313 314 if type(name) == types.StringType: 315 name = unicode(name) 316 317 assert(type(project) == types.UnicodeType) 318 assert(type(name) == types.UnicodeType) 319 320 if locale is not None: 321 if type(locale) == types.UnicodeType: 322 locale = str(locale) 323 324 assert(type(locale) == types.StringType) 325 return (project, name, locale) in self._iniCache 326 327 if not self._fallback: 328 loc = self._localeSet[0] 329 return (project, name, loc) in self._iniCache 330 331 332 for locale in self._localeSet: 333 if (project, name, locale) in self._iniCache: 334 return True 335 336 return (project, name, 'all') in self._iniCache
337 338
339 - def getValueForKey(self, project, name, locale=None):
340 """ 341 Returns the unicode string value that was specified 342 in one or more eggs resource ini files (default is 343 "resource.ini") for the given project and name. or 344 None if not found. 345 346 The locale is an optional argument. By default 347 the locale set is searched in fallback order 348 (if fallback=True in the initialize or 349 setLocale method) until a key is found. 350 351 However, if a locale is specified the method will only 352 search for a key in the resource ini files for the 353 given locale. 354 355 B{Example}: 356 357 If you have a C{resource.ini} file containing the following 358 entry:: 359 360 [MyProject::fr] 361 myimage = /resources/imgs/myimage.png 362 363 then:: 364 365 >>> print eggRMInstance.getValueForKey("MyProject", 366 ... "myimage", "fr") 367 /resource/imgs/myimage.png 368 369 @raise UnicodeDecodeError: 370 @raise UnicodeEncodeError: 371 372 @param project: A project is a root namespace under which 373 resources and localizations exist. 374 375 A project name matches an egg name. 376 An egg's info file can contain resource 377 and localizations for more than one project. 378 379 The project name must be either an ASCII 380 C{str} or C{unicode}. 381 382 @type project: ASCII C{str} or C{unicode} 383 384 @param name: name is the key to lookup in 385 a resource ini file to retrieve the 386 value specifed. For example, 387 myname = this is my value. 388 389 The name must be either an ASCII 390 C{str} or C{unicode}. 391 392 @type name: ASCII C{str} or C{unicode} 393 394 395 @param locale: Optional argument that if specified 396 tells the method to only return True 397 if key is present in one or more 398 ini files for the given locale. 399 This parameter if specified must contain 400 a valid language / country locale 401 i.e. "en_US" or "en" 402 403 @type locale: C{unicode} or ASCII C{str} 404 405 @return: C{unicode} value or C{None} if not found 406 """ 407 408 res = self._getTupleForKey(project, name, locale) 409 410 return res and res[1] or None
411
412 - def isDirectory(self, project, name, locale=None):
413 """ 414 Returns True if: 415 416 1. One or more resource ini files have an 417 entry for the key contained in the name 418 parameter. 419 420 2. The entry is a valid directory path. 421 422 The locale is an optional argument. By default 423 the locale set is searched in fallback order 424 (if fallback=True in the initialize or 425 setLocale method) until a key is found. 426 If no key found the method returns False. 427 428 However, if a locale is specified the method will only 429 search for a key in the resource ini files for the 430 given locale. 431 432 @raise UnicodeDecodeError: 433 @raise UnicodeEncodeError: 434 435 @param project: 436 437 A project is a root namespace under which 438 resources and localizations exist. 439 440 A project name matches an egg name. 441 An egg's info file can contain resource 442 and localizations for more than one project. 443 444 The project name must be either an ASCII 445 C{str} or C{unicode}. 446 447 @type project: ASCII C{str} or C{unicode} 448 449 @param name: name is the key to lookup in 450 a resource ini file to retrieve the 451 value specifed. For example, 452 myname = this is my value. 453 454 The name must be either an ASCII 455 C{str} or C{unicode}. 456 457 @type name: ASCII C{str} or C{unicode} 458 459 460 @param locale: Optional argument that if specified 461 tells the method to only return True 462 if key is present in one or more 463 ini files for the given locale. 464 This parameter if specified must contain 465 a valid language / country locale 466 i.e. "en_US" or "en" 467 468 @type locale: C{unicode} or ASCII C{str} 469 470 @return: C{bool} True if the name is found and 471 the entry for that name is a valid directory 472 path in an egg otherwise False 473 """ 474 475 res = self._getTupleForKey(project, name, locale) 476 477 if res is not None: 478 dist, value = res 479 480 return dist.metadata_isdir( 481 value.encode(self._iniEncoding)) 482 483 return False
484 485
486 - def listDirectory(self, project, name, locale=None):
487 """ 488 Returns a C{list} of C{unicode} values containing the 489 names of files in the directory entry for the 490 given project and name. The listDirectory 491 method will not return the names of sub directories 492 only files in the directory for the given project and 493 name. 494 495 The locale is an optional argument. By default 496 the locale set is searched in fallback order 497 (if fallback=True in the initialize or 498 setLocale method) until a key is found. 499 If no key found the method returns False. 500 501 However, if a locale is specified the method will only 502 search for a key in the resource ini files for the 503 given locale. 504 505 @raise UnicodeDecodeError: 506 @raise UnicodeEncodeError: 507 @raise NameError: 508 @raise OSError: 509 510 @param project: A project is a root namespace under which 511 resources and localizations exist. 512 513 A project name matches an egg name. 514 An egg's info file can contain resource 515 and localizations for more than one project. 516 517 The project name must be either an ASCII 518 C{str} or C{unicode}. 519 520 @type project: ASCII C{str} or C{unicode} 521 522 @param name: name is the key to lookup in 523 a resource ini file to retrieve the 524 value specifed. For example, 525 myname = this is my value. 526 527 The name must be either an ASCII 528 C{str} or C{unicode}. 529 530 @type name: ASCII C{str} or C{unicode} 531 532 533 @param locale: Optional argument that if specified 534 tells the method to only return True 535 if key is present in one or more 536 ini files for the given locale. 537 This parameter if specified must contain 538 a valid language / country locale 539 i.e. "en_US" or "en" 540 541 @type locale: C{unicode} or ASCII C{str} 542 543 @return: C{list} of C{unicode} filenames 544 """ 545 546 res = self._getTupleForKey(project, name, locale) 547 548 if res is None: 549 self._raiseNameError(project, name, locale) 550 551 dist, value = res 552 553 dir = dist.metadata_listdir( 554 value.encode(self._iniEncoding)) 555 556 for i in xrange(0, len(dir)): 557 dir[i] = unicode(dir[i], self._iniEncoding) 558 559 return dir
560
561 - def hasResource(self, project, name, locale=None):
562 """ 563 Returns True if: 564 1. one or more resource ini files have an 565 entry for the key contained in the 566 name parameter. 567 568 2. The entry must be a valid path to a file 569 in the same egg as resource ini. 570 571 B{Example}: 572 573 If you have a C{resource.ini} file containing the following 574 entry:: 575 576 [MyProject::fr] 577 myResource=/resources/myresource.png 578 579 then:: 580 581 >>> print eggRMInstance.hasResource("MyProject", 582 ... "myResource", "fr") 583 True 584 585 @raise UnicodeDecodeError: 586 @raise UnicodeEncodeError: 587 588 The locale is an optional argument. By default 589 the locale set is searched in fallback order 590 (if fallback=True in the initialize or setLocale 591 method) until a key is found. If no key found 592 the method returns False. 593 594 However, if a locale is specified the method will only 595 search for a key in the resource ini files for the 596 given locale. 597 598 @param project: A project is a root namespace under which 599 resources and localizations exist. 600 601 A project name matches an egg name. 602 An egg's info file can contain resource 603 and localizations for more than one project. 604 605 The project name must be either an ASCII 606 C{str} or C{unicode}. 607 608 @type project: ASCII C{str} or C{unicode} 609 610 @param name: name is the key to lookup in 611 a resource ini file to retrieve the 612 value specifed. For example, 613 myname = this is my value. 614 615 The name must be either an ASCII 616 C{str} or C{unicode}. 617 618 @type name: ASCII C{str} or C{unicode} 619 620 621 @param locale: Optional argument that if specified 622 tells the method to only return True 623 if key is present in one or more 624 ini files for the given locale. 625 This parameter if specified must contain 626 a valid language / country locale 627 i.e. "en_US" or "en" 628 629 @type locale: C{unicode} or ASCII C{str} 630 631 @return: C{bool} True if the name key points to at least 632 one resource in an egg otherwise False. 633 """ 634 635 res = self._getTupleForKey(project, name, locale) 636 637 if res is not None: 638 dist, value = res 639 return dist.has_metadata( 640 value.encode(self._iniEncoding)) 641 642 return False
643 644
645 - def getResourceAsStream(self, project, name, locale=None):
646 """ 647 Returns a C{file} handle to the resource for 648 the given project and name. 649 650 The locale is an optional argument. By default 651 the locale set is searched in fallback order 652 (if fallback=True in the initialize or 653 setLocale method) until a key is found. If 654 no key found the method returns False. 655 656 However, if a locale is specified the method will only 657 search for a key in the resource ini files for the 658 given locale. 659 660 @raise UnicodeDecodeError: 661 @raise UnicodeEncodeError: 662 @raise NameError: 663 @raise IOError: 664 665 @param project: A project is a root namespace under which 666 resources and localizations exist. 667 668 A project name matches an egg name. 669 An egg's info file can contain resource 670 and localizations for more than one project. 671 672 The project name must be either an ASCII 673 C{str} or C{unicode}. 674 675 @type project: ASCII C{str} or C{unicode} 676 677 @param name: name is the key to lookup in 678 a resource ini file to retrieve the 679 value specifed. For example, 680 myname = this is my value. 681 682 The name must be either an ASCII 683 C{str} or C{unicode}. 684 685 @type name: ASCII C{str} or C{unicode} 686 687 688 @param locale: Optional argument that if specified 689 tells the method to only return True 690 if key is present in one or more 691 ini files for the given locale. 692 This parameter if specified must contain 693 a valid language / country locale 694 i.e. "en_US" or "en" 695 696 @type locale: C{unicode} or ASCII C{str} 697 698 @return: C{file} handle to the resource 699 """ 700 701 res = self._getTupleForKey(project, name, locale) 702 703 if res is None: 704 self._raiseNameError(project, name, locale) 705 706 dist, value = res 707 708 return StringIO(dist.get_metadata( 709 value.encode(self._iniEncoding)))
710 711
712 - def getResourceAsLines(self, project, name, locale=None, 713 encoding='UTF-8'):
714 """ 715 Returns a C{generator} containing a list of non-blank 716 non-comment lines in a resource file for the given project 717 and name. 718 719 The locale is an optional argument. By default 720 the locale set is searched in fallback order 721 (if fallback=True in the initialize or 722 setLocale method) until a key is found. 723 If no key found the method returns False. 724 725 However, if a locale is specified the method will only 726 search for a key in the resource ini files for the 727 given locale. 728 729 @raise UnicodeDecodeError: 730 @raise UnicodeEncodeError: 731 @raise NameError: 732 @raise IOError: 733 @raise LookupError: 734 735 B{Example}: 736 737 Imagine you have a resource.ini file that contains the 738 following:: 739 740 [MyProject::all] 741 myDocument = README.txt 742 743 Then you might retrieve all lines from the ``README.txt`` 744 file via:: 745 746 >>> lines = eggRMInstance.getResourceAsLines("MyProject", 747 ... "myDocument", 748 ... "all") 749 750 >>> for line in lines: 751 ... print line 752 753 @param project: A project is a root namespace under which 754 resources and localizations exist. 755 756 A project name matches an egg name. 757 An egg's info file can contain resource 758 and localizations for more than one project. 759 760 The project name must be either an ASCII 761 C{str} or C{unicode}. 762 763 @type project: ASCII C{str} or C{unicode} 764 765 @param name: name is the key to lookup in 766 a resource ini file to retrieve the 767 value specifed. For example, 768 myname = this is my value. 769 770 The name must be either an ASCII 771 C{str} or C{unicode}. 772 773 @type name: ASCII C{str} or C{unicode} 774 775 @param locale: Optional argument that if specified 776 tells the method to only return True 777 if key is present in one or more 778 ini files for the given locale. 779 This parameter if specified must contain 780 a valid language / country locale 781 i.e. "en_US" or "en" 782 783 @type locale: C{unicode} or ASCII C{str} 784 785 786 @param encoding: The character set encoding of the 787 resource file. This encoding will be 788 used to convert C{str} values contained 789 in the file to C{unicode}. 790 The default encoding is "UTF-8". 791 792 @type encoding: ASCII C{str} or C{unicode} 793 794 @return: C{generator} list of non-blank non-comment 795 C{unicode} lines. 796 """ 797 798 return pkg_resources.yield_lines(self.getResourceAsString( 799 project, name, locale, encoding))
800 801
802 - def getResourceAsString(self, project, name, locale=None, 803 encoding='UTF-8'):
804 """ 805 Returns a C{unicode} string containing the contents of 806 the resource file for the given project and name. 807 808 The locale is an optional argument. By default 809 the locale set is searched in fallback order 810 (if fallback=True in the initialize or 811 setLocale method) until a key is found. 812 If no key found the method returns False. 813 814 However, if a locale is specified the method will only 815 search for a key in the resource ini files for the 816 given locale. 817 818 819 B{Example}: 820 821 If you have a C{resource.ini} file containing the following 822 entry:: 823 824 [MyProject::all] 825 myDocument = README.txt 826 827 Then you could retrieve the entire contents of C{README.txt} 828 as a C{unicode} string via:: 829 830 >>> f = eggRMInstance.getResourceAsString("MyProject", 831 ... "myDocument", 832 ... "all") 833 834 >>> f 835 u'This is the text contained in the readme file' 836 837 @raise UnicodeDecodeError: 838 @raise UnicodeEncodeError: 839 @raise NameError: 840 @raise IOError: 841 @raise LookupError: 842 843 844 @param project: A project is a root namespace under which 845 resources and localizations exist. 846 847 A project name matches an egg name. 848 An egg's info file can contain resource 849 and localizations for more than one project. 850 851 The project name must be either an ASCII 852 C{str} or C{unicode}. 853 854 @type project: ASCII C{str} or C{unicode} 855 856 @param name: name is the key to lookup in 857 a resource ini file to retrieve the 858 value specifed. For example, 859 myname = this is my value. 860 861 The name must be either an ASCII 862 C{str} or C{unicode}. 863 864 @type name: ASCII C{str} or C{unicode} 865 866 867 @param locale: Optional argument that if specified 868 tells the method to only return True 869 if key is present in one or more 870 ini files for the given locale. 871 This parameter if specified must contain 872 a valid language / country locale 873 i.e. "en_US" or "en" 874 875 @type locale: C{unicode} or ASCII C{str} 876 877 @param encoding: The character set encoding of the 878 resource file. This encoding will be 879 used to convert C{str} values contained 880 in the file to C{unicode}. 881 The default encoding is "UTF-8". 882 883 @type encoding: ASCII C{str} or C{unicode} 884 885 @return: C{unicode} contents of the resource file. 886 """ 887 888 res = self._getTupleForKey(project, name, locale) 889 890 if res is None: 891 self._raiseNameError(project, name, locale) 892 893 dist, value = res 894 895 bytes = dist.get_metadata(value.encode(self._iniEncoding)) 896 return unicode(bytes, encoding)
897
898 - def getText(self, project, name, txt, *args):
899 """ 900 Returns a C{unicode} string containing the localized 901 value for key txt in the given project. The name 902 parameter points to a key in a resource ini file that 903 contain a value entry pointing to a gettext .mo 904 resource in the same egg. 905 906 An optional additional argument can be specified as the 907 default value to return if no localized is found. 908 909 The txt parameter will be returned by 910 L{EggTranslations.getText} if no localized value found 911 for the txt parameter. 912 913 However, if the default value argument is passed, 914 that value will be returned instead of text. 915 916 Example where there in no localized value for 917 txt parameter "Hello World": 918 919 >>> eggRMInstance.getText("MyProject", "catalog", 920 ... "Hello World") 921 u'Hello World' 922 >>> 923 >>> eggRMInstance.getText("MyProject", "catalog", 924 ... "Hello World", 925 ... None) 926 None 927 >>> 928 929 If fallback was set to True in the 930 L{EggTranslations.initialize} method or the 931 L{EggTranslations.setLocaleSet} method, the 932 L{EggTranslations.getText} method will search all 933 locales in the locale set till a gettext mo 934 translation is found for the txt parameter. 935 936 If fallback was set to False in the 937 L{EggTranslations.initialize} method 938 or the L{EggTranslations.setLocaleSet} method, the 939 L{EggTranslations.getText} method will only search 940 the current locale, which is the first locale in the 941 locale set for a gettext mo translation for 942 the txt parameter. 943 944 Note that the "all" default locale can not 945 contain any key value pairs that point to gettext 946 .mo files. 947 948 If a .mo gettext value is found in the "all" default 949 locale, the .mo file will not be loaded by 950 the L{EggTranslations}. 951 952 953 B{Example}: 954 955 A resource.ini file contains the following entry:: 956 957 [MyProject::fr] 958 catalog = locale/fr/MyProject.mo 959 960 The locale/fr/myproject.mo file contains a 961 localization of "Hello" to "Bonjour". Then, calling 962 L{EggTranslations.getText} looks this up in the 963 C{.mo} file:: 964 965 >>> egRMInstance.initialize("fr") 966 >>> eggRMInstance.getText("MyProject", "catalog", 967 ... "Hello") 968 u'Bonjour' 969 970 @raise UnicodeDecodeError: 971 972 @param project: A project is a root namespace under which 973 resources and localizations exist. 974 975 A project name matches an egg name. 976 An egg's info file can contain resource 977 and localizations for more than one project. 978 979 The project name must be either an ASCII 980 C{str} or C{unicode}. 981 982 @type project: ASCII C{str} or C{unicode} 983 984 @param name: name is the key to lookup in 985 a resource ini file to retrieve the 986 value specifed. For example, 987 myname = this is my value. 988 989 The name must be either an ASCII 990 C{str} or C{unicode}. 991 992 @type name: ASCII C{str} or C{unicode} 993 994 @param txt: The default text string which is used 995 as look up key to retrieve a localized 996 value from a gettext .mo file. 997 998 The default text string is usual 999 the English version of the text. The 1000 .mo gettext files will contain 1001 localizations of the English version 1002 with the English version as the key. 1003 1004 @type txt: ASCII C{str} or C{unicode} 1005 1006 @param args: An optional argument which if passed 1007 will be returned if no localzation 1008 found for txt. The type of the 1009 return value in the args list 1010 has no limitations. 1011 @type args: C{list} 1012 1013 @return: C{unicode} localized text or 1014 either the original txt argument 1015 or the default value in args if no 1016 localization found. 1017 """ 1018 assert(self._init, True) 1019 1020 if type(project) == types.StringType: 1021 project = unicode(project) 1022 1023 if type(name) == types.StringType: 1024 name = unicode(name) 1025 1026 if type(txt) == types.StringType: 1027 txt = unicode(txt) 1028 1029 assert(type(project) == types.UnicodeType) 1030 assert(type(name) == types.UnicodeType) 1031 assert(type(txt) == types.UnicodeType) 1032 1033 if self._fallback: 1034 for locale in self._localeSet: 1035 key = (project, name, locale) 1036 1037 # The first found EggTranslation for 1038 # locale set is the root for fallback 1039 if key in self._gtCache: 1040 return self._gtCache[key].ugettext(txt, *args) 1041 1042 return args and args[0] or txt 1043 1044 key = (project, name, self._localeSet[0]) 1045 1046 if key in self._gtCache: 1047 return self._gtCache[key].ugettext(txt, *args) 1048 1049 1050 return args and args[0] or txt
1051
1052 - def hasFallback(self):
1053 """ 1054 Returns True if fallback was set to True in either the 1055 L{EggTranslations.initialize} method or the 1056 L{EggTranslations.setLocaleSet} method. 1057 1058 @return: C{boolean} True if fallback set to True 1059 in initialize or setLocaleSet methods 1060 otherwise False. 1061 """ 1062 assert(self._init, True) 1063 return self._fallback
1064
1065 - def hasTranslation(self, project, name, locale):
1066 """ 1067 returns True if the gettext mo file for the given locale, 1068 project, and name is loaded. 1069 1070 @param project: A project is a root namespace under which 1071 resources and localizations exist. 1072 1073 A project name matches an egg name. 1074 An egg's info file can contain resource 1075 and localizations for more than one project. 1076 1077 The project name must be either an ASCII 1078 C{str} or C{unicode}. 1079 1080 @type project: ASCII C{str} or C{unicode} 1081 1082 @param name: name is the key to lookup in 1083 a resource ini file to retrieve the 1084 value specifed. For example, 1085 myname = this is my value. 1086 1087 The name must be either an ASCII 1088 C{str} or C{unicode}. 1089 1090 @type name: ASCII C{str} or C{unicode} 1091 1092 1093 @param locale: The locale to scan for a gettext .mo translation. 1094 This parameter must contain a valid 1095 language / country locale i.e. "en_US" or "en". 1096 1097 @type locale: C{unicode} or ASCII C{str} 1098 1099 @return: C{bool} True if the .mo gettext file exists for the 1100 project, name, and locale otherwise False. 1101 """ 1102 1103 assert(self._init, True) 1104 1105 try: 1106 return self._moCache[(project, name)].has_key(locale) 1107 except Exception: 1108 return False
1109
1110 - def getAvailableLocales(self, project):
1111 """ 1112 Returns a C{list} of the locales that have registered one or more 1113 key value pairs for the given project. 1114 1115 @param project: A project is a root namespace under which 1116 resources and localizations exist. 1117 1118 A project name matches an egg name. 1119 An egg's info file can contain resource 1120 and localizations for more than one project. 1121 1122 The project name must be either an ASCII 1123 C{str} or C{unicode}. 1124 1125 @type project: ASCII C{str} or C{unicode} 1126 1127 @return: C{list} of C{str} locale language / country codes. 1128 """ 1129 1130 assert(self._init, True) 1131 1132 try: 1133 return self._localeCache[project] 1134 except Exception: 1135 return []
1136
1137 - def getINIFileName(self):
1138 """ 1139 Returns the C{unicode} file name of the 1140 resource ini files. The default for the resource 1141 ini file is "resource.ini". 1142 1143 The name of the resource ini file is set 1144 in the L{EggTranslations.initialize} method. 1145 1146 @return: C{unicode} the name of the resource ini file. 1147 """ 1148 1149 assert(self._init, True) 1150 return self._iniFileName
1151
1152 - def getLocaleSet(self):
1153 """ 1154 Returns a C{list} of valid C{str} locale language / country 1155 codes. The C{list} is arranged in ascending fallback order. 1156 1157 @return: C{list} of C{str} locale language / country codes. 1158 """ 1159 1160 assert(self._init, True) 1161 return self._localeSet
1162
1163 - def setLocaleSet(self, localeSet, fallback=True):
1164 """ 1165 Resets the L{EggTranslations} locale set C{list}. 1166 1167 Resetting the locale set includes unloading all gettext 1168 .mo translations, loading the the gettext .mo translations 1169 for the current locale set, and setting the gettext locale 1170 fallback order if the fallback parameter is set to True. 1171 1172 Note the initial locale set for the L{EggTranslations} 1173 must be set in the L{EggTranslations.initialize} 1174 method. 1175 1176 Note, setting the L{EggTranslations} locale set 1177 also adds the language code as a fallback for language / 1178 county code locale definitions when fallback is set to True. 1179 If the locale set contains 'fr_CA' this method will also add 1180 to the locale set 'fr' as a fallback for 'fr_CA'. 1181 1182 @raise UnicodeEncodeError: 1183 @raise NameError: 1184 1185 @param localeSet: A C{unicode} or C{str} or C{list} 1186 containing locale country and language 1187 codes. The value(s) must be able to 1188 be converted to ASCII. 1189 1190 @type localeSet: ASCII C{str} or C{unicode} or 1191 C{list} containing ASCII 1192 C{str} or C{unicode} values 1193 1194 @param fallback: Indicates whether locale set fallback should 1195 take place. If set to True, the 1196 EggTranslations will search all locales 1197 in the locale set till a resource or 1198 gettext mo translation file is found. If 1199 set to False the EggTranslations will 1200 only try to locate a resource or 1201 gettext mo translation file for the 1202 current locale which is the first locale 1203 in the locale set. 1204 1205 1206 @type fallback: C{boolean} 1207 """ 1208 1209 assert(self._init, True) 1210 1211 self._fallback = fallback 1212 1213 if type(localeSet) == types.ListType: 1214 tmpLocaleSet = localeSet 1215 1216 for i in xrange(0, len(tmpLocaleSet)): 1217 if type(tmpLocaleSet[i]) == types.UnicodeType: 1218 tmpLocaleSet[i] = str(tmpLocaleSet[i]) 1219 1220 # All entries in the locale set must be strings 1221 assert(type(tmpLocaleSet[i]) == types.StringType) 1222 1223 1224 elif type(localeSet) == types.StringType: 1225 tmpLocaleSet = localeSet.split(",") 1226 1227 elif type(localeSet) == types.UnicodeType: 1228 #Convert to Python str from unicode 1229 tmpLocaleSet = str(localeSet).split(",") 1230 else: 1231 raise NameError("localeSet must of type str, unicode, \ 1232 or List") 1233 1234 tmpLocaleSet = list(self.normalizeLocale(stripEncodingCode(loc)) 1235 for loc in tmpLocaleSet) 1236 1237 for loc in tmpLocaleSet: 1238 if not self.isValidLocaleForm(loc): 1239 raise NameError, "Invalid locale name found '%s'" % (loc,) 1240 1241 #Deallocate the _gtCache and its contents 1242 self._gtCache = None 1243 self._gtCache = {} 1244 1245 if self._fallback: 1246 self._localeSet = list(self.yieldFallbackLocales(tmpLocaleSet)) 1247 else: 1248 self._localeSet = tmpLocaleSet 1249 1250 if __debug__: 1251 logger.debug(u"Setting Locale Set to: %s", 1252 self._localeSet) 1253 1254 keys = self._moCache.keys() 1255 1256 for key in keys: 1257 project, name = key 1258 1259 if not self._fallback: 1260 # Create EggTranslation for the primary locale 1261 # (self._localeSet[0]) only if 1262 # there is an mo file declaration in the ini. 1263 1264 locale = self._localeSet[0] 1265 1266 if not locale in self._moCache[key]: 1267 #Continue past the EggTranslation code 1268 continue 1269 1270 dist, mofile = self._moCache[key][locale] 1271 1272 # The mofile variable is an str not 1273 # unicode 1274 bytes = dist.get_metadata(mofile) 1275 trans = DefaultTranslations(StringIO(bytes)) 1276 1277 self._gtCache[(project, name, locale)] = trans 1278 1279 if __debug__: 1280 logger.debug(u"%s EggTranslation %s " \ 1281 "(No Fallback)", key, locale) 1282 1283 #Continue past the fallback code 1284 continue 1285 1286 root = None 1287 1288 for locale in self._localeSet: 1289 if locale not in self._moCache[key]: 1290 #Continue past the EggTranslation code 1291 continue 1292 1293 dist, mofile = self._moCache[key][locale] 1294 1295 bytes = dist.get_metadata(mofile) 1296 trans = DefaultTranslations(StringIO(bytes)) 1297 1298 self._gtCache[(project, name, locale)] = trans 1299 1300 if root is None: 1301 root = trans 1302 1303 if __debug__: 1304 logger.debug(u"%s Root EggTranslation %s", 1305 key, locale) 1306 else: 1307 root.add_fallback(trans) 1308 1309 if __debug__: 1310 logger.debug(u"%s Adding Fallback %s", key, 1311 locale)
1312
1313 - def normalizeLocale(self, locale):
1314 """ 1315 Normalizes the C{str} locale to 1316 lower case all lang codes and 1317 upper case all country codes. 1318 1319 Thus if passed "Fr_cA" this method 1320 would return "fr_CA". 1321 1322 If passed "FR" this method would return 1323 "fr" 1324 1325 @param locale: a C{str} locale 1326 @type locale: ASCII C{str} 1327 1328 @return: C{str} normalized version of the 1329 locale. 1330 """ 1331 1332 assert(type(locale) == types.StringType) 1333 1334 components = locale.split("_") 1335 1336 if len(components) < 2: 1337 return locale.lower() 1338 else: 1339 return "%s_%s" % (components[0].lower(), components[-1].upper())
1340
1341 - def isValidLocaleForm(self, locale):
1342 """ 1343 Returns True if the C{str} locale passed 1344 has a valid form which is either lang code ("es") 1345 or lang code / country code ("es_UY"). 1346 1347 This method does not validate whether 1348 the C{str} matches a valid ISO code. 1349 Only that the form of the C{str} is correct. 1350 1351 @param locale: a C{str} locale 1352 @type locale: ASCII C{str} 1353 1354 @return: C{boolean} True if locale has a valid form 1355 otherwise False 1356 1357 """ 1358 assert(type(locale) == types.StringType) 1359 1360 size = len(locale) 1361 1362 if size == 2: 1363 return True 1364 1365 if size == 5 and locale[2] == '_': 1366 return True 1367 1368 return False
1369
1370 - def yieldFallbackLocales(self, localeSet):
1371 """ 1372 Adds the lang code, if not already present, 1373 to the localeSet as a fallback to the 1374 lang country code. 1375 1376 Thus if passed ["fr_CA", "en_US", "es"] this method 1377 would return ["fr_CA", "fr", "en_US", "en", "es"] 1378 1379 @param localeSet: a C{list} containing ASCII C{str} locales 1380 @type localeSet: C{list} 1381 1382 @return: C{list} containing original locale set C{str}'s 1383 and lang code fallbacks. 1384 """ 1385 1386 assert(type(localeSet) == types.ListType) 1387 1388 for locale in localeSet: 1389 yield locale 1390 if (hasCountryCode(locale)): 1391 langCode = stripCountryCode(locale) 1392 if not langCode in localeSet: 1393 yield langCode
1394 1395
1396 - def getDebugString(self):
1397 """ 1398 Returns a C{str} representation of the 1399 L{EggTranslations}'s egg loading values suitable 1400 for debugging using print, the logging package, or a 1401 UI dialog box. 1402 1403 The structure of the debug string is as follows:: 1404 1405 EggTranslations 1406 ========================= 1407 INI FILE: ResourceFileName (Encoding) 1408 LOCALE SET: [localeSetValues] 1409 FALLBACK: True | False 1410 1411 EggName 1412 =============================== 1413 1414 ProjectName 1415 --------------------- 1416 [LocaleName] 1417 entryKey=entryValue 1418 gettextKey=getTextMoFile (LOADED | NOT_LOADED) 1419 1420 1421 Here's an additional example output using real values:: 1422 1423 EggTranslations 1424 ========================= 1425 INI FILE: 'resources.ini' (UTF-8) 1426 LOCALE SET: ['fr_CA', 'fr'] 1427 FALLBACK: True 1428 1429 MyProject 0.1 1430 =============================== 1431 1432 myProject 1433 ------------------------- 1434 [all] 1435 splashScreenImage = imgs/splash.png 1436 readme = README.txt 1437 1438 myAlternateProject 1439 ------------------------- 1440 [all] 1441 splashScreenImage = alternate/imgs/splash.png 1442 readme=alternate/README.txt 1443 1444 MyProject.fr 0.1 1445 =============================== 1446 1447 myProject 1448 ------------------------ 1449 [fr_CA] 1450 splashScreenImage = locale/fr/imgs/splash.png 1451 readme = locale/fr/README.txt 1452 catalog= locale/fr/myProject.mo (LOADED) 1453 1454 myAlternateProject 1455 ------------------------ 1456 [fr_CA] 1457 splashScreenImage = alternate/locale/fr/imgs/splash.png 1458 readme = alternate/locale/fr/README.txt 1459 catalog = alternate/locale/fr/myProject.mo (LOADED) 1460 1461 @return: C{str} debug string of L{EggTranslations} 1462 current configuration in the UTF-8 encoding. 1463 """ 1464 tree = {} 1465 sBuffer = [] 1466 1467 keys = self._iniCache.keys() 1468 1469 # Build a tree of dictionaries 1470 # which can be traversed to render 1471 # the debug string in the correct order 1472 for key in keys: 1473 project, name, locale = key 1474 dist, value = self._iniCache[key] 1475 1476 if not dist in tree: 1477 tree[dist] = {} 1478 1479 if not project in tree[dist]: 1480 tree[dist][project] = {} 1481 1482 if not locale in tree[dist][project]: 1483 tree[dist][project][locale] = {} 1484 1485 tree[dist][project][locale][name] = value 1486 1487 1488 sBuffer.append(u"\n\n%s\n" % (self._NAME)) 1489 sBuffer.append(u"=============================\n") 1490 sBuffer.append(u" INI FILE: '%s' (%s)\n" % ( 1491 self._iniFileName, 1492 self._iniEncoding)) 1493 1494 sBuffer.append(u" LOCALE SET: %s\n" % (self._localeSet)) 1495 sBuffer.append(u" FALLBACK: %s\n" % (self._fallback)) 1496 sBuffer.append(u"\n") 1497 1498 dists = tree.keys() 1499 1500 for dist in dists: 1501 sBuffer.append(u" %s\n" % (dist)) 1502 sBuffer.append(u" ================================\n\n") 1503 1504 for project in tree[dist]: 1505 sBuffer.append(u" %s\n" % (project)) 1506 sBuffer.append(u" --------------------" \ 1507 "---------\n") 1508 1509 1510 for locale in tree[dist][project]: 1511 sBuffer.append(u" [%s]\n" % (locale)) 1512 1513 for name in tree[dist][project][locale]: 1514 val = tree[dist][project][locale][name] 1515 1516 state = "" 1517 1518 if val.endswith(u".mo"): 1519 key = (project, name, locale) 1520 1521 if key in self._gtCache: 1522 state = " (LOADED)" 1523 else: 1524 state = u" (NOT_LOADED)" 1525 1526 sBuffer.append(u" %s = %s%s\n" % ( 1527 name, val, state)) 1528 1529 sBuffer.append(u"\n") 1530 1531 sBuffer.append(u"\n") 1532 1533 sBuffer.append(u"\n") 1534 1535 return (u"".join(sBuffer)).encode("UTF-8", "replace")
1536 1537
1538 - def _parseINIFiles(self, dist):
1539 """ 1540 Callback method passed to 1541 C{pkg_resources.add_activation_listener} method. 1542 1543 For each egg distribution contained in the dist parameter: 1544 1. Parses the resource ini file (default name 1545 is "resource.ini") for each egg that contains one. 1546 2. Builds a cache of resources based on project, 1547 locale, and name. 1548 3. For each .mo value for a given project, 1549 locale, and name cache the file path to the 1550 .mo gettext file. 1551 1552 @raise INIParsingException: 1553 @raise LookupError: 1554 @raise UnicodeDecodeError: 1555 @raise UnicodeEncodeError: 1556 1557 @param dist: An egg package distribution 1558 @type dist: C{pkg_resources.Distribution} 1559 """ 1560 1561 if __debug__: 1562 logger.debug(u"EggTranslations parsing %s", dist) 1563 1564 #Convert from unicode to byte str since the 1565 # pkg_resources API only works with str's. 1566 iniFile = self._iniFileName.encode(self._iniEncoding) 1567 1568 if dist.has_metadata(iniFile): 1569 1570 if __debug__: 1571 logger.debug(u"Found '%s' for project %s", 1572 self._iniFileName, dist) 1573 1574 ini_unicode_data = None 1575 1576 try: 1577 s = dist.get_metadata(iniFile) 1578 ini_unicode_data = unicode(s, self._iniEncoding) 1579 except Exception, e: 1580 s = u"unable to load ini file in %s encoding. (%s)" 1581 1582 self._raiseParseError(dist, s, self._iniEncoding, e) 1583 1584 # The call to the pkg_resources.split_sections 1585 # strips comments and blank lines 1586 ini_map = None 1587 try: 1588 data = pkg_resources.split_sections(ini_unicode_data) 1589 ini_map = dict(data) 1590 except Exception, e: 1591 s = u"one or more invalid ini token found: %s" 1592 self._raiseParseError(dist, s, e) 1593 1594 ini_keys = ini_map.keys() 1595 1596 if len(ini_keys) == 1 and ini_keys[0] is None: 1597 1598 # Invalid tokens found in project definition. 1599 # Represented in map as 1600 # {None: [ONE_OR_MORE_VALUES]} 1601 1602 if len(ini_map[None]): 1603 s = u"one or more invalid ini token found: %s" 1604 self._raiseParseError(dist, s, ini_map[None]) 1605 1606 # If the resource ini file does not 1607 # contain any project definitions 1608 # i.e. [myproject::all] then return 1609 if __debug__: 1610 logger.debug(u"%s no projects defined in '%s'", 1611 dist, self._iniFileName) 1612 return 1613 1614 ini_values = ini_map.values() 1615 1616 for i in xrange(0, len(ini_map)): 1617 project, locales = (None, None) 1618 try: 1619 project, locales = ini_keys[i].split("::") 1620 except: 1621 s = u"invalid project format found '[%s]'. " \ 1622 "Should be [project_name::locale_name]" 1623 1624 self._raiseParseError(dist, s, ini_keys[i]) 1625 1626 #Trim leading and trailing whitespace 1627 project = project.strip() 1628 locales = locales.strip() 1629 1630 if not locales or not project: 1631 s = u"invalid project format found '[%s]'. " \ 1632 "Should be [project_name::locale_name]" 1633 1634 self._raiseParseError(dist, s, ini_keys[i]) 1635 1636 for locale in locales.split(","): 1637 locale = locale.strip() 1638 1639 if not locale: 1640 s = u"invalid project format found '[%s]'. " \ 1641 "Should be [project_name::locale_name]" 1642 1643 self._raiseParseError(dist, s, ini_keys[i]) 1644 1645 if not ini_values[i]: 1646 logger.warn("%s %s [%s] no key " \ 1647 "value entries defined", dist, 1648 self._iniFileName, ini_keys[i]) 1649 1650 try: 1651 if locale.lower() == 'all': 1652 # Normalize 'all' to lowercase 1653 locale = locale.lower() 1654 else: 1655 #try converting the locale from unicode 1656 #to ascii str and normalize it 1657 locale = self.normalizeLocale(str(locale)) 1658 1659 if self._localeCache.has_key(project): 1660 locales = self._localeCache[project] 1661 else: 1662 locales = [] 1663 1664 locales.append(locale) 1665 1666 # Add the locale to list of locales 1667 # available to this project. 1668 self._localeCache[project] = locales 1669 except: 1670 s = u"Invalid locale found. Unable to " \ 1671 "convert to ASCII: %s" 1672 1673 self._raiseParseError(dist, s, locale) 1674 1675 if locale != 'all' and not \ 1676 self.isValidLocaleForm(locale): 1677 s = u"invalid locale format found '%s'" 1678 1679 self._raiseParseError(dist, s, locale) 1680 1681 for line in ini_values[i]: 1682 name, value = (None, None) 1683 try: 1684 name, value = line.split("=", 1) 1685 except: 1686 s = u"invalid key value pair found " \ 1687 "'%s' in [%s]. Should be " \ 1688 "key = value" 1689 1690 self._raiseParseError(dist, s, line, 1691 ini_keys[i]) 1692 1693 if value.rfind("#") != -1: 1694 value, comment = value.split("#", 1) 1695 1696 #Trim leading and trailing whitespace 1697 value = value.strip() 1698 name = name.strip() 1699 1700 key = (project, name, locale) 1701 1702 self._iniCache[key] = (dist, value) 1703 1704 if __debug__: 1705 logger.debug(u"[%s::%s] '%s = %s' " \ 1706 "added to ini cache", 1707 project, locale, name, value) 1708 1709 if value.endswith(u".mo") and not \ 1710 locale == 'all': 1711 # Caches the file resource 1712 # location of each .mo file. 1713 # 1714 # This cache will be used by 1715 # setLocaleSet method to 1716 # load the EggTranslations 1717 # and build the fallback order 1718 # if fallback set to True 1719 1720 isValidPath = False 1721 bVal = value.encode(self._iniEncoding) 1722 1723 try: 1724 isValidPath = dist.has_metadata(bVal) 1725 except: 1726 pass 1727 1728 if not isValidPath: 1729 s = u" mo file entry '%s' does not " \ 1730 "point to a valid resource " \ 1731 "path" 1732 self._raiseParseError(dist, s, line) 1733 1734 pKey = (project, name) 1735 # Add the byte version of .mo path 1736 # to moCache 1737 pVal = (dist, bVal) 1738 1739 if not pKey in self._moCache: 1740 self._moCache[pKey] = {} 1741 1742 self._moCache[pKey][locale] = pVal 1743 1744 if __debug__: 1745 logger.debug(u"[%s::%s] %s added " \ 1746 "%s to mo cache", 1747 project, locale, name, 1748 value) 1749 1750 elif value.endswith(u".mo"): 1751 logger.warn(u"gettext .mo file " \ 1752 "definition '%s' found in " \ 1753 "'all' default locale. " \ 1754 "This file will not be loaded.", 1755 value)
1756 1757
1758 - def _getTupleForKey(self, project, name, locale=None):
1759 assert(self._init, True) 1760 1761 if type(project) == types.StringType: 1762 project = unicode(project) 1763 1764 if type(name) == types.StringType: 1765 name = unicode(name) 1766 1767 1768 assert(type(project) == types.UnicodeType) 1769 assert(type(name) == types.UnicodeType) 1770 1771 if locale is None and not self._fallback: 1772 locale = self._localeSet[0] 1773 1774 if locale is not None: 1775 if type(locale) == types.UnicodeType: 1776 locale = str(locale) 1777 1778 assert(type(locale) == types.StringType) 1779 key = (project, name, locale) 1780 1781 if key in self._iniCache: 1782 return self._iniCache[key] 1783 1784 return None 1785 1786 for locale in self._localeSet: 1787 key = (project, name, locale) 1788 1789 if key in self._iniCache: 1790 return self._iniCache[key] 1791 1792 key = (project, name, 'all') 1793 1794 if key in self._iniCache: 1795 return self._iniCache[key] 1796 1797 return None
1798
1799 - def _raiseNameError(self, project, name, locale):
1800 s = u"No match found for [%s::%s] %s" \ 1801 % (project, locale and locale or self._localeSet, name) 1802 1803 raise NameError(s.encode("UTF-8", "replace"))
1804
1805 - def _raiseParseError(self, dist, errTxt, *args):
1806 s = u"Error Parsing '%s' for Project '%s' " \ 1807 % (self._iniFileName, dist) 1808 1809 if args: 1810 errTxt = errTxt % args 1811 1812 s += errTxt 1813 1814 raise INIParsingException(s.encode("UTF-8", "replace"))
1815
1816 -def stripCountryCode(locale):
1817 """ 1818 Removes the country code from a language / country 1819 code locale. If passed "es_UY" would return "es" 1820 1821 @param locale: a valid C{str} language / country code 1822 locale 1823 @type locale: ASCII C{str} 1824 1825 @return: C{str} with country code removed 1826 """ 1827 assert(type(locale) == types.StringType) 1828 1829 return (locale.split('_')[0]).lower()
1830
1831 -def hasCountryCode(locale):
1832 """ 1833 Returns True if the locale passed 1834 contains a country code such as "es_UY" 1835 otherwise False. 1836 1837 @param locale: a C{str} locale 1838 @type locale: ASCII C{str} 1839 1840 @return: C{boolean} True if locale contains country code 1841 otherwise False 1842 """ 1843 1844 assert(type(locale) == types.StringType) 1845 1846 return len(locale) == 5 and locale[2] == '_'
1847 1848
1849 -def stripEncodingCode(locale):
1850 """ 1851 Strips additional information 1852 off of a locale definition 1853 1854 A locale can contain additional 1855 information beyond the two digit 1856 language and country codes. 1857 1858 For example an encoding can be 1859 specified: such as "en_US.UTF-8" 1860 1861 If passed "en_US.UTF-8" this method 1862 would return "en_US" 1863 1864 @param locale: a C{str} locale 1865 @type locale: ASCII C{str} 1866 1867 @return: C{str} stripped version of locale 1868 or original locale C{str} if no 1869 stripping was required. 1870 """ 1871 1872 assert(type(locale) == types.StringType) 1873 1874 dot = locale.find(".") 1875 if dot != -1: 1876 locale = locale[:dot] 1877 1878 return locale
1879