#FEATURE by cg expecco_2_9_0 expecco_2_9_0_win75_lx36 expecco_2_9_1
authorClaus Gittinger <cg@exept.de>
Thu, 28 Apr 2016 22:36:49 +0200
changeset 32861ea9a6fbe2b4
parent 3285 5b8697869e72
child 3287 0bddeff854d4
#FEATURE by cg
class: Tools::InternationalLanguageTranslationEditor
class definition
added:5 methods
comment/format in:
#extractTranslationsFromClass:
#extractTranslationsFromMethod:
#search
changed:15 methods
many improvements;
extract remembers methods; browse-button to navigate there;
recorder working;
Tools__InternationalLanguageTranslationEditor.st
     1.1 --- a/Tools__InternationalLanguageTranslationEditor.st	Thu Apr 28 20:41:04 2016 +0200
     1.2 +++ b/Tools__InternationalLanguageTranslationEditor.st	Thu Apr 28 22:36:49 2016 +0200
     1.3 @@ -20,7 +20,7 @@
     1.4  		closeSearchBar searchTextModifiedHolder searchNextText
     1.5  		searchBarImageInfoLabelHolder searchPreviousText searchBoxVisible
     1.6  		searchBarInfoLabelHolder searchTextHolder searchTextView
     1.7 -		searchBoxView translationsPanel lastPackage'
     1.8 +		searchBoxView translationsPanel lastPackage methodsUsingKey'
     1.9  	classVariableNames:'LastExtractedClass LastExtractedApplicationClass
    1.10  		LastExtractedProject LastProject'
    1.11  	poolDictionaries:''
    1.12 @@ -28,7 +28,7 @@
    1.13  !
    1.14  
    1.15  Object subclass:#AccessCollectingPseudoResourcePack
    1.16 -	instanceVariableNames:'collectedKeys realResourcePack'
    1.17 +	instanceVariableNames:'collectedKeys realResourcePack watchingTranslationEditor'
    1.18  	classVariableNames:''
    1.19  	poolDictionaries:''
    1.20  	privateIn:InternationalLanguageTranslationEditor
    1.21 @@ -94,6 +94,45 @@
    1.22      "Created: / 04-03-2006 / 09:07:19 / cg"
    1.23  ! !
    1.24  
    1.25 +!InternationalLanguageTranslationEditor class methodsFor:'help spec'!
    1.26 +
    1.27 +flyByHelpSpec
    1.28 +    <resource: #help>
    1.29 +
    1.30 +    ^ super flyByHelpSpec addPairsFrom:#(
    1.31 +
    1.32 +#searchBox
    1.33 +'Show a search box at the bottom to search for substrings in the string keys'
    1.34 +
    1.35 +#browseReferringMethods
    1.36 +'Browse methods which refer to this string'
    1.37 +
    1.38 +)
    1.39 +! !
    1.40 +
    1.41 +!InternationalLanguageTranslationEditor class methodsFor:'help specs'!
    1.42 +
    1.43 +helpSpec
    1.44 +    "This resource specification was automatically generated
    1.45 +     by the UIHelpTool of ST/X."
    1.46 +
    1.47 +    "Do not manually edit this!! If it is corrupted,
    1.48 +     the UIHelpTool may not be able to read the specification."
    1.49 +
    1.50 +    "
    1.51 +     UIHelpTool openOnClass:Tools::InternationalLanguageTranslationEditor    
    1.52 +    "
    1.53 +
    1.54 +    <resource: #help>
    1.55 +
    1.56 +    ^ super helpSpec addPairsFrom:#(
    1.57 +
    1.58 +#searchBox
    1.59 +''
    1.60 +
    1.61 +)
    1.62 +! !
    1.63 +
    1.64  !InternationalLanguageTranslationEditor class methodsFor:'image specs'!
    1.65  
    1.66  closeSearchBarIcon
    1.67 @@ -452,7 +491,7 @@
    1.68                        )
    1.69                      
    1.70                     )
    1.71 -                   handles: (Any 0.33333333333333004 0.66666666666667007 1.0)
    1.72 +                   handles: (Any 0.3333333333333301 0.66666666666667018 1.0)
    1.73                   )
    1.74                  )
    1.75                
    1.76 @@ -479,13 +518,13 @@
    1.77                  (LabelSpec
    1.78                     label: 'Search:'
    1.79                     name: 'SearchLabel'
    1.80 -                   layout: (LayoutFrame 30 0 5 0 81 0 27 0)
    1.81 +                   layout: (LayoutFrame 30 0 5 0 100 0 27 0)
    1.82                     translateLabel: true
    1.83                     adjust: right
    1.84                   )
    1.85                  (InputFieldSpec
    1.86                     name: 'SearchEntryField'
    1.87 -                   layout: (LayoutFrame 87 0 5 0 244 0 27 0)
    1.88 +                   layout: (LayoutFrame 100 0 5 0 257 0 27 0)
    1.89                     model: searchTextHolder
    1.90                     immediateAccept: true
    1.91                     acceptOnReturn: true
    1.92 @@ -498,7 +537,7 @@
    1.93                  (ActionButtonSpec
    1.94                     label: 'searchNextIcon'
    1.95                     name: 'SearchNextButton'
    1.96 -                   layout: (LayoutFrame 251 0 5 0 272 0 26 0)
    1.97 +                   layout: (LayoutFrame 264 0 5 0 285 0 26 0)
    1.98                     hasCharacterOrientedLabel: false
    1.99                     translateLabel: true
   1.100                     model: searchNextText
   1.101 @@ -506,7 +545,7 @@
   1.102                  (ActionButtonSpec
   1.103                     label: 'searchPreviousIcon'
   1.104                     name: 'searchPreviousButton'
   1.105 -                   layout: (LayoutFrame 279 0 5 0 300 0 26 0)
   1.106 +                   layout: (LayoutFrame 292 0 5 0 313 0 26 0)
   1.107                     hasCharacterOrientedLabel: false
   1.108                     translateLabel: true
   1.109                     model: searchPreviousText
   1.110 @@ -514,14 +553,14 @@
   1.111                  (CheckBoxSpec
   1.112                     label: 'Ignore case'
   1.113                     name: 'IgnoreCaseCheckBox'
   1.114 -                   layout: (LayoutFrame 309 0 5 0 505 0 27 0)
   1.115 +                   layout: (LayoutFrame 322 0 5 0 518 0 27 0)
   1.116                     model: ignoreCaseHolder
   1.117                     translateLabel: true
   1.118                   )
   1.119                  (LabelSpec
   1.120                     label: 'SearchBarImageInfoLabel'
   1.121                     name: 'SearchBarImageInfoLabel'
   1.122 -                   layout: (LayoutFrame 511 0 5 0 535 0 27 0)
   1.123 +                   layout: (LayoutFrame 524 0 5 0 548 0 27 0)
   1.124                     hasCharacterOrientedLabel: false
   1.125                     translateLabel: true
   1.126                     labelChannel: searchBarImageInfoLabelHolder
   1.127 @@ -529,7 +568,7 @@
   1.128                  (LabelSpec
   1.129                     label: 'SearchBarInfoLabel'
   1.130                     name: 'SearchBarInfoLabel'
   1.131 -                   layout: (LayoutFrame 538 0 5 0 816 0 27 0)
   1.132 +                   layout: (LayoutFrame 551 0 5 0 829 0 27 0)
   1.133                     translateLabel: true
   1.134                     labelChannel: searchBarInfoLabelHolder
   1.135                     adjust: left
   1.136 @@ -563,36 +602,45 @@
   1.137  
   1.138      ^
   1.139       #(Menu
   1.140 -	(
   1.141 -	 (MenuItem
   1.142 -	    label: 'Set Current NameSpace'
   1.143 -	    itemValue: changeLastNameSpace
   1.144 -	    translateLabel: true
   1.145 -	  )
   1.146 -	 (MenuItem
   1.147 -	    label: 'Search String in Current NameSpace'
   1.148 -	    itemValue: searchStringInLastNameSpace
   1.149 -	    translateLabel: true
   1.150 -	  )
   1.151 -	 (MenuItem
   1.152 -	    label: '-'
   1.153 -	    isVisible: #false
   1.154 -	  )
   1.155 -	 (MenuItem
   1.156 -	    label: 'Set Current Package'
   1.157 -	    itemValue: changeLastPackage
   1.158 -	    translateLabel: true
   1.159 -	    isVisible: #false
   1.160 -	  )
   1.161 -	 (MenuItem
   1.162 -	    label: 'Search String in Current Package'
   1.163 -	    itemValue: searchStringInLastPackage
   1.164 -	    translateLabel: true
   1.165 -	    isVisible: #false
   1.166 -	  )
   1.167 -	 )
   1.168 -	nil
   1.169 -	nil
   1.170 +        (
   1.171 +         (MenuItem
   1.172 +            label: 'Browse Methods Containing this String'
   1.173 +            itemValue: browseReferringMethods
   1.174 +            translateLabel: true
   1.175 +          )
   1.176 +         (MenuItem
   1.177 +            label: '-'
   1.178 +            isVisible: #false
   1.179 +          )
   1.180 +         (MenuItem
   1.181 +            label: 'Set Current NameSpace...'
   1.182 +            itemValue: changeLastNameSpace
   1.183 +            translateLabel: true
   1.184 +          )
   1.185 +         (MenuItem
   1.186 +            label: 'Search String in Current NameSpace'
   1.187 +            itemValue: searchStringInLastNameSpace
   1.188 +            translateLabel: true
   1.189 +          )
   1.190 +         (MenuItem
   1.191 +            label: '-'
   1.192 +            isVisible: #false
   1.193 +          )
   1.194 +         (MenuItem
   1.195 +            label: 'Set Current Package...'
   1.196 +            itemValue: changeLastPackage
   1.197 +            translateLabel: true
   1.198 +            isVisible: #false
   1.199 +          )
   1.200 +         (MenuItem
   1.201 +            label: 'Search String in Current Package'
   1.202 +            itemValue: searchStringInLastPackage
   1.203 +            translateLabel: true
   1.204 +            isVisible: #false
   1.205 +          )
   1.206 +         )
   1.207 +        nil
   1.208 +        nil
   1.209        )
   1.210  !
   1.211  
   1.212 @@ -690,6 +738,10 @@
   1.213                    indication: showMissingTranslationsOnly
   1.214                  )
   1.215                 (MenuItem
   1.216 +                  label: 'Show Search Box'
   1.217 +                  indication: searchBoxVisible
   1.218 +                )
   1.219 +               (MenuItem
   1.220                    label: '-'
   1.221                  )
   1.222                 (MenuItem
   1.223 @@ -824,7 +876,6 @@
   1.224           (MenuItem
   1.225              label: 'Save'
   1.226              itemValue: menuSave
   1.227 -            translateLabel: true
   1.228              isButton: true
   1.229              labelImage: (ResourceRetriever XPToolbarIconLibrary saveImageIcon)
   1.230            )
   1.231 @@ -834,14 +885,12 @@
   1.232           (MenuItem
   1.233              label: 'Add Translation'
   1.234              itemValue: addTranslation
   1.235 -            translateLabel: true
   1.236              isButton: true
   1.237              labelImage: (ResourceRetriever XPToolbarIconLibrary newRowIcon)
   1.238            )
   1.239           (MenuItem
   1.240              label: 'Remove Translation'
   1.241              itemValue: removeTranslation
   1.242 -            translateLabel: true
   1.243              isButton: true
   1.244              labelImage: (ResourceRetriever XPToolbarIconLibrary removeRowIcon)
   1.245            )
   1.246 @@ -849,12 +898,10 @@
   1.247              label: '-'
   1.248            )
   1.249           (MenuItem
   1.250 -            label: 'Search'
   1.251 -            itemValue: search
   1.252 -            translateLabel: true
   1.253 -            isButton: true
   1.254 -            shortcutKey: Ctrlf
   1.255 -            labelImage: (ResourceRetriever #'Tools::InternationalLanguageTranslationEditor' searchToolBarIcon)
   1.256 +            activeHelpKey: browseReferringMethods
   1.257 +            label: 'Browse'
   1.258 +            itemValue: browseReferringMethods
   1.259 +            labelImage: (ResourceRetriever ToolbarIconLibrary systemBrowserIcon)
   1.260            )
   1.261           (MenuItem
   1.262              label: ''
   1.263 @@ -862,11 +909,20 @@
   1.264           (MenuItem
   1.265              label: 'Stop Application'
   1.266              itemValue: stopApplication
   1.267 -            translateLabel: true
   1.268              isButton: true
   1.269              isVisible: stopApplicationIconVisibleHolder
   1.270              labelImage: (ResourceRetriever XPToolbarIconLibrary stop16x16Icon)
   1.271            )
   1.272 +         (MenuItem
   1.273 +            activeHelpKey: searchBox
   1.274 +            label: 'Search'
   1.275 +            isButton: true
   1.276 +            startGroup: right
   1.277 +            hideMenuOnActivated: false
   1.278 +            indication: searchBoxVisible
   1.279 +            shortcutKey: Ctrlf
   1.280 +            labelImage: (ResourceRetriever #'Tools::InternationalLanguageTranslationEditor' searchToolBarIcon)
   1.281 +          )
   1.282           )
   1.283          nil
   1.284          nil
   1.285 @@ -903,14 +959,14 @@
   1.286              label: '-'
   1.287            )
   1.288           (MenuItem
   1.289 +            label: 'Extract from Package...'
   1.290 +            itemValue: extractTranslationsFromProject
   1.291 +          )
   1.292 +         (MenuItem
   1.293              label: 'Extract from Class...'
   1.294              itemValue: extractTranslationsFromClass
   1.295            )
   1.296           (MenuItem
   1.297 -            label: 'Extract from Project...'
   1.298 -            itemValue: extractTranslationsFromProject
   1.299 -          )
   1.300 -         (MenuItem
   1.301              label: 'Extract from NameSpace...'
   1.302              itemValue: extractTranslationsFromNameSpace
   1.303            )
   1.304 @@ -1265,7 +1321,14 @@
   1.305  searchBoxVisible
   1.306  
   1.307      searchBoxVisible isNil ifTrue:[
   1.308 -	searchBoxVisible := false asValue.
   1.309 +        searchBoxVisible := false asValue.
   1.310 +        searchBoxVisible 
   1.311 +            onChangeEvaluate:[ 
   1.312 +                self updateToolVisibility.
   1.313 +                searchBoxVisible value ifTrue:[
   1.314 +                    searchTextView takeFocus.
   1.315 +                ].
   1.316 +            ].
   1.317      ].
   1.318      ^ searchBoxVisible.
   1.319  
   1.320 @@ -1553,6 +1616,7 @@
   1.321  initialize
   1.322      modified := false.
   1.323      inSingleFileMode := false.
   1.324 +    methodsUsingKey := Dictionary new.
   1.325      super initialize
   1.326  !
   1.327  
   1.328 @@ -1627,6 +1691,21 @@
   1.329     self selectedKeyRow value:index
   1.330  !
   1.331  
   1.332 +browseReferringMethods
   1.333 +    |selectedKey methods browser|
   1.334 +
   1.335 +    selectedKey := self selectedKey.
   1.336 +    selectedKey isNil ifTrue:[^ Dialog information: 'No selected key'].
   1.337 +
   1.338 +    methods := methodsUsingKey at:selectedKey ifAbsent:nil.
   1.339 +    methods isEmptyOrNil ifTrue:[
   1.340 +        Dialog information:(resources stringWithCRs:'oops - no method remembered.\Please rerun the extract from XXX menu operation').
   1.341 +        ^ self.
   1.342 +    ].    
   1.343 +    browser := UserPreferences systemBrowserClass browseMethods:methods.
   1.344 +    browser autoSearch:selectedKey ignoreCase:true.
   1.345 +!
   1.346 +
   1.347  changeLastNameSpace
   1.348  
   1.349      |nameSpace defaultNameSpace|
   1.350 @@ -1939,36 +2018,36 @@
   1.351      |applicationClass newTranslations pseudoPack app startSelector|
   1.352  
   1.353      monitoredApplication notNil ifTrue:[
   1.354 -	monitoredApplication terminate.
   1.355 -	[monitoredApplication notNil] whileTrue:[
   1.356 -	    Delay waitForSeconds:0.1
   1.357 -	].
   1.358 +        monitoredApplication terminate.
   1.359 +        [monitoredApplication notNil] whileTrue:[
   1.360 +            Delay waitForSeconds:0.1
   1.361 +        ].
   1.362      ].
   1.363  
   1.364      applicationClass := Dialog
   1.365 -		requestClass:'Application class to start and collect translations from:'
   1.366 -		okLabel:'OK'
   1.367 -		initialAnswer:(lastExtractedApplicationClass ? LastExtractedApplicationClass ).
   1.368 +                requestClass:'Application class to start and collect translations from:'
   1.369 +                okLabel:'OK'
   1.370 +                initialAnswer:(lastExtractedApplicationClass ? LastExtractedApplicationClass ).
   1.371      applicationClass isNil ifTrue:[^ self ].
   1.372 -    applicationClass isNamespace ifTrue:[
   1.373 -	Dialog warn:'Entered class is a NameSpace'.
   1.374 -	^ self.
   1.375 +    applicationClass isNameSpace ifTrue:[
   1.376 +        Dialog warn:'Entered class is a NameSpace'.
   1.377 +        ^ self.
   1.378      ].
   1.379  
   1.380      applicationClass isVisualStartable ifTrue:[
   1.381 -	startSelector := #open
   1.382 +        startSelector := #open
   1.383      ] ifFalse:[
   1.384 -	startSelector := Dialog
   1.385 -		    request:'Entered class seems to be no application class. Ok to start using selector:'
   1.386 -		    initialAnswer:((applicationClass respondsTo:#'start')
   1.387 -					ifTrue:#'start'
   1.388 -					ifFalse:#'new')
   1.389 -		    okLabel:'START'
   1.390 -		    title:'Start Application'.
   1.391 -	startSelector isNil ifTrue:[
   1.392 -	    ^ self
   1.393 -	].
   1.394 -	startSelector := startSelector asSymbol.
   1.395 +        startSelector := Dialog
   1.396 +                    request:'Entered class seems to be no application class. Ok to start using selector:'
   1.397 +                    initialAnswer:((applicationClass respondsTo:#'start')
   1.398 +                                        ifTrue:#'start'
   1.399 +                                        ifFalse:#'new')
   1.400 +                    okLabel:'START'
   1.401 +                    title:'Start Application'.
   1.402 +        startSelector isNil ifTrue:[
   1.403 +            ^ self
   1.404 +        ].
   1.405 +        startSelector := startSelector asSymbol.
   1.406      ].
   1.407  
   1.408      lastExtractedApplicationClass := LastExtractedApplicationClass := applicationClass.
   1.409 @@ -1977,21 +2056,25 @@
   1.410  
   1.411      pseudoPack := AccessCollectingPseudoResourcePack new.
   1.412      pseudoPack realResourcePack:(applicationClass classResources).
   1.413 +    pseudoPack watchingTranslationEditor:self.
   1.414  
   1.415      self stopApplicationIconVisibleHolder value:true.
   1.416  
   1.417 -    monitoredApplication := [
   1.418 -	[
   1.419 -	    app := applicationClass new.
   1.420 -	    app perform:startSelector.
   1.421 -	    app window waitUntilVisible.
   1.422 -	    app window waitUntilClosed.
   1.423 -	] ensure:[
   1.424 -	    app closeRequest.
   1.425 -	    self stopApplicationIconVisibleHolder value:false.
   1.426 -	    monitoredApplication := nil.
   1.427 -	].
   1.428 -    ] fork.
   1.429 +    monitoredApplication := 
   1.430 +        [
   1.431 +            [
   1.432 +                app := applicationClass new.
   1.433 +                app resources:pseudoPack.
   1.434 +                
   1.435 +                app perform:startSelector.
   1.436 +                app window waitUntilVisible.
   1.437 +                app window waitUntilClosed.
   1.438 +            ] ensure:[
   1.439 +                app closeRequest.
   1.440 +                self stopApplicationIconVisibleHolder value:false.
   1.441 +                monitoredApplication := nil.
   1.442 +            ].
   1.443 +        ] fork.
   1.444  !
   1.445  
   1.446  searchStringInLastNameSpace
   1.447 @@ -2025,24 +2108,39 @@
   1.448      | selectedKey browser lastSearchPatterns|
   1.449  
   1.450      selectedKey := self selectedKey.
   1.451 -    selectedKey isNil ifTrue:[^Dialog information: 'No selected key'].
   1.452 +    selectedKey isNil ifTrue:[^ Dialog information: 'No selected key'].
   1.453 +
   1.454      browser := NewSystemBrowser new "open".
   1.455      browser allButOpen.
   1.456 +    
   1.457      lastSearchPatterns := browser lastSearchPatterns.
   1.458      (lastSearchPatterns notNil and:[lastSearchPatterns first ~= selectedKey]) ifTrue:[
   1.459 -	browser lastSearchPatterns addFirst: selectedKey
   1.460 +        browser lastSearchPatterns addFirst: selectedKey
   1.461      ].
   1.462      SearchDialog lastStringSearchArea: #currentPackage.
   1.463      lastPackage isNil ifTrue:[
   1.464 -	self changeLastPackage.
   1.465 +        self changeLastPackage.
   1.466      ].
   1.467      lastPackage notNil ifTrue:[
   1.468  "/        browser navigationState selectedClasses value: lastNameSpace allClasses.
   1.469 -	browser navigationState packageFilter value: (OrderedCollection with:lastPackage).
   1.470 -	browser navigationState selectedProjects value: (OrderedCollection with:lastPackage).
   1.471 +        browser navigationState packageFilter value: (OrderedCollection with:lastPackage).
   1.472 +        browser navigationState selectedProjects value: (OrderedCollection with:lastPackage).
   1.473      ].
   1.474      self withWaitCursorDo:[
   1.475 -	browser browseMenuMethodsWithString
   1.476 +        browser 
   1.477 +            askForMethodAndSpawnSearchTitle:'String to Search for in Sources:'
   1.478 +            browserLabel:'Methods containing "%1"'
   1.479 +            searchWith:#( #'findString:in:ignoreCase:match:' #'findString:inMethods:ignoreCase:match:' )
   1.480 +            searchWhat:#string
   1.481 +            searchArea:#currentPackage
   1.482 +            withCaseIgnore:false
   1.483 +            withTextEntry:false
   1.484 +            withMatch:true
   1.485 +            withMethodList:false
   1.486 +            setSearchPattern:[:brwsr :string :ignoreCase :doMatch|
   1.487 +                                brwsr autoSearchPattern:string ignoreCase:ignoreCase.
   1.488 +                             ]
   1.489 +            initialText:selectedKey "/ does not work: ('''*',selectedKey,'*''') check match!!               
   1.490      ].
   1.491  ! !
   1.492  
   1.493 @@ -2116,22 +2214,39 @@
   1.494  !InternationalLanguageTranslationEditor methodsFor:'private-key extraction'!
   1.495  
   1.496  addAllTranslations:newTranslations
   1.497 +    "merge found xlations into the list of already present xlations"
   1.498 +    
   1.499      |newTranslationKeys stringKeys nonStringKeys|
   1.500  
   1.501      newTranslationKeys := newTranslations select:[:k | k notEmptyOrNil and:[k isString not or:[k isBlank not]]].
   1.502      newTranslationKeys := newTranslationKeys select:[:k | (keyStringsToLanguageMappings includesKey:k) not].
   1.503 -    newTranslationKeys := newTranslationKeys
   1.504 -                                collect:[:k |
   1.505 -                                        (k endsWith:' ...') ifTrue:[
   1.506 -                                            k copyButLast:4.
   1.507 -                                        ] ifFalse:[(k endsWith:'...') ifTrue:[
   1.508 -                                            k copyButLast:3.
   1.509 -                                        ] ifFalse:[
   1.510 -                                            ('\.:?=,!! ' includes:k last) ifTrue:[
   1.511 -                                                k copyButLast:1.
   1.512 -                                            ] ifFalse:[
   1.513 -                                                k
   1.514 -                                        ]]]].
   1.515 +    "/ follow the common-xlations algrithm of ResourcePack
   1.516 +    "/ (which knows how to xlate strings with additional special chars.)
   1.517 +    newTranslationKeys := 
   1.518 +        newTranslationKeys collect:[:oldKey |
   1.519 +            |newKey methods|
   1.520 +            
   1.521 +            (oldKey endsWith:' ...') ifTrue:[
   1.522 +                newKey := oldKey copyButLast:4.
   1.523 +            ] ifFalse:[ (oldKey endsWith:'...') ifTrue:[
   1.524 +                newKey := oldKey copyButLast:3.
   1.525 +            ] ifFalse:[ ('\.:?=,!! ' includes:oldKey last) ifTrue:[
   1.526 +                newKey := oldKey copyButLast:1.
   1.527 +            ] ifFalse:[ ((oldKey first == $() and:[ oldKey last == $) ]) ifTrue:[
   1.528 +                newKey := oldKey copyFrom:2 to:oldKey size - 1
   1.529 +            ] ifFalse:[ ((oldKey first == $[) and:[ oldKey last == $] ]) ifTrue:[
   1.530 +                newKey := oldKey copyFrom:2 to:oldKey size - 1
   1.531 +            ] ifFalse:[
   1.532 +                newKey :=oldKey
   1.533 +            ]]]]].
   1.534 +            "/ must attach oldKey-methods to newKey
   1.535 +            methods := methodsUsingKey at:oldKey ifAbsent:nil.
   1.536 +            methods notNil ifTrue:[
   1.537 +                (methodsUsingKey at:newKey ifAbsentPut:[Set new]) addAll:methods
   1.538 +            ].    
   1.539 +            newKey
   1.540 +        ].
   1.541 +        
   1.542      newTranslationKeys := newTranslationKeys asSet.
   1.543      newTranslationKeys := newTranslationKeys select:[:k | (keyStringsToLanguageMappings includesKey:k) not].
   1.544  
   1.545 @@ -2159,13 +2274,17 @@
   1.546              newTranslations addAll:( self extractTranslationsFromMethod:eachMethod ).
   1.547          ].
   1.548      ].
   1.549 -    newTranslations := newTranslations select:[:eachTranslation|
   1.550 -        (aClass resources at:eachTranslation ifAbsent:nil) isNil
   1.551 -    ].
   1.552 +    
   1.553 +    newTranslations := 
   1.554 +        newTranslations select:[:eachTranslation|
   1.555 +            (aClass resources at:eachTranslation ifAbsent:nil) isNil
   1.556 +        ].
   1.557      ^ newTranslations
   1.558  !
   1.559  
   1.560  extractTranslationsFromHelpSpecMethod:aMethod
   1.561 +    "return strings which need translation from a help-spec method"
   1.562 +
   1.563      |codeStrings matcher parseTree resourceKeys|
   1.564  
   1.565      parseTree := RBParser
   1.566 @@ -2192,6 +2311,7 @@
   1.567                      "/ a ^ #(...)
   1.568                      aNode value isLiteralArray ifTrue:[
   1.569                          aNode value value pairWiseDo:[:helpKey :helpString |
   1.570 +                            self rememberMethod:aMethod usingKey:helpString.
   1.571                              resourceKeys add:helpString.
   1.572                          ].
   1.573                      ].    
   1.574 @@ -2199,27 +2319,20 @@
   1.575                      sel := aNode selector.
   1.576                      (sel startsWith:'addPairsFrom:') ifTrue:[
   1.577                          argNode := aNode arguments at:1.
   1.578 -                        argNode isLiteral ifTrue:[
   1.579 +                        argNode isLiteralArray ifTrue:[
   1.580                              arg := argNode value.
   1.581 -                            arg isArray ifTrue:[
   1.582 -                                arg doWithIndex:[:el :index |
   1.583 -                                    index even ifTrue:[
   1.584 -                                        el isString ifTrue:[
   1.585 -                                            resourceKeys add:el.
   1.586 -                                        ]
   1.587 -                                    ].
   1.588 +                            arg doWithIndex:[:el :index |
   1.589 +                                index even ifTrue:[
   1.590 +                                    el isString ifTrue:[
   1.591 +                                        self rememberMethod:aMethod usingKey:el.
   1.592 +                                        resourceKeys add:el.
   1.593 +                                    ]
   1.594                                  ].
   1.595 -                            ] ifFalse:[
   1.596 -                                Transcript
   1.597 -                                    showCR:(resources
   1.598 -                                            string:'Cannot derive resourceKey from non-array in %1 in %2'
   1.599 -                                            with:argNode formattedCode
   1.600 -                                            with:aMethod selector).
   1.601                              ].
   1.602                          ] ifFalse:[
   1.603                              Transcript halt
   1.604                                  showCR:(resources
   1.605 -                                            string:'Cannot derive resourceKey from non-literal: %1 in %2'
   1.606 +                                            string:'Cannot derive resourceKey from non-literal array: %1 in %2'
   1.607                                              with:argNode formattedCode
   1.608                                              with:aMethod selector).
   1.609                          ].
   1.610 @@ -2233,6 +2346,8 @@
   1.611  !
   1.612  
   1.613  extractTranslationsFromMenuSpecMethod:aMethod
   1.614 +    "return strings which need translation from a menu-spec method"
   1.615 +
   1.616      |menu resourceKeys|
   1.617  
   1.618      menu := aMethod mclass theNonMetaclass perform:aMethod selector.
   1.619 @@ -2246,6 +2361,7 @@
   1.620      menu allItemsDo:[:aMenuItem |
   1.621          aMenuItem translateLabel ifTrue:[
   1.622              (aMenuItem isSeparatorItem or:[aMenuItem isMenuSlice])  ifFalse:[
   1.623 +                self rememberMethod:aMethod usingKey:aMenuItem label.
   1.624                  resourceKeys add:aMenuItem label.
   1.625              ]
   1.626          ]
   1.627 @@ -2254,6 +2370,8 @@
   1.628  !
   1.629  
   1.630  extractTranslationsFromMethod:aMethod
   1.631 +    "return strings which need translation from a method."
   1.632 +    
   1.633      |mResources|
   1.634  
   1.635      mResources := aMethod resources.
   1.636 @@ -2277,7 +2395,9 @@
   1.637  !
   1.638  
   1.639  extractTranslationsFromMethodsCode:aMethod
   1.640 -"/method:mthd selector:sel inClass:cls matchesParseTreeMatcher:aMatcher
   1.641 +    "return strings which need translation from a normal method.
   1.642 +     detects messages to the resource translation mechanism"
   1.643 +
   1.644      |codeStrings matcher parseTree resourceKeys|
   1.645  
   1.646      parseTree := RBParser
   1.647 @@ -2308,6 +2428,7 @@
   1.648                  ((sel startsWith:'string:') or:[(sel startsWith:'at:') or:[sel startsWith:'stringWithCRs:']]) ifTrue:[
   1.649                      keyStringArgNode := aNode arguments at:1.
   1.650                      (keyStringArg := self literalStringOrStringConcatenation:keyStringArgNode) notNil ifTrue:[
   1.651 +                        self rememberMethod:aMethod usingKey:keyStringArg.
   1.652                          resourceKeys add:keyStringArg.
   1.653                      ] ifFalse:[
   1.654                          Transcript
   1.655 @@ -2331,39 +2452,46 @@
   1.656  !
   1.657  
   1.658  extractTranslationsFromTableColumnsSpecMethod:aMethod
   1.659 +    "return strings which need translation from a table-spec method"
   1.660 +
   1.661      |columnDescription resourceKeys|
   1.662  
   1.663      columnDescription := aMethod mclass theNonMetaclass perform:aMethod selector.
   1.664      columnDescription isNil ifTrue:[ ^ #() ].
   1.665  
   1.666      (columnDescription first isKindOf:DataSetColumnSpec) ifFalse:[
   1.667 -	columnDescription := columnDescription collect:[:el | DataSetColumnSpec new fromLiteralArrayEncoding:el].
   1.668 +        columnDescription := columnDescription collect:[:el | DataSetColumnSpec new fromLiteralArrayEncoding:el].
   1.669      ].
   1.670  
   1.671      resourceKeys := Set new.
   1.672      columnDescription do:[:aColumnSpec |
   1.673 -	aColumnSpec translateLabel ifTrue:[
   1.674 -	    resourceKeys add:aColumnSpec label.
   1.675 -	]
   1.676 +        aColumnSpec translateLabel ifTrue:[
   1.677 +            self rememberMethod:aMethod usingKey:aColumnSpec label.
   1.678 +            resourceKeys add:aColumnSpec label.
   1.679 +        ]
   1.680      ].
   1.681      ^ resourceKeys
   1.682  !
   1.683  
   1.684  extractTranslationsFromUISpecMethod:aMethod
   1.685 +    "return strings which need translation from a UI-spec method"
   1.686 +    
   1.687      |spec resourceKeys visitor|
   1.688  
   1.689      spec := aMethod mclass theNonMetaclass perform:aMethod selector.
   1.690      spec isNil ifTrue:[ ^ #() ].
   1.691  
   1.692      (spec isKindOf:UISpecification) ifFalse:[
   1.693 -	spec := UISpecification from:spec
   1.694 +        spec := UISpecification from:spec
   1.695      ].
   1.696  
   1.697      resourceKeys := Set new.
   1.698  
   1.699      visitor := UISpecVisitor new.
   1.700      spec acceptVisitor:visitor.
   1.701 -
   1.702 +    visitor translatedLabels do:[:each |
   1.703 +        self rememberMethod:aMethod usingKey:each.
   1.704 +    ].
   1.705      ^ visitor translatedLabels
   1.706  !
   1.707  
   1.708 @@ -2389,6 +2517,16 @@
   1.709          ].
   1.710      ].
   1.711      ^ nil
   1.712 +!
   1.713 +
   1.714 +recordNewTranslation:aString
   1.715 +    "called from recorder, when the monitored application does a translation"
   1.716 +    
   1.717 +    self addAllTranslations:{ aString }
   1.718 +!
   1.719 +
   1.720 +rememberMethod:aMethod usingKey:aKey
   1.721 +    (methodsUsingKey at:aKey ifAbsentPut:[Set new]) add:aMethod
   1.722  ! !
   1.723  
   1.724  !InternationalLanguageTranslationEditor methodsFor:'queries'!
   1.725 @@ -2926,7 +3064,8 @@
   1.726  !
   1.727  
   1.728  search
   1.729 -
   1.730 +    "make the searchbox visible"
   1.731 +    
   1.732      self searchBoxVisible value: true.
   1.733      self updateToolVisibility.
   1.734      searchTextView takeFocus.
   1.735 @@ -2970,6 +3109,27 @@
   1.736  
   1.737  realResourcePack:something
   1.738      realResourcePack := something.
   1.739 +!
   1.740 +
   1.741 +watchingTranslationEditor:something
   1.742 +    watchingTranslationEditor := something.
   1.743 +! !
   1.744 +
   1.745 +!InternationalLanguageTranslationEditor::AccessCollectingPseudoResourcePack methodsFor:'resource pack protocol'!
   1.746 +
   1.747 +forwardFor:aString
   1.748 +    collectedKeys isNil ifTrue:[
   1.749 +        collectedKeys := Set new.
   1.750 +    ].
   1.751 +    collectedKeys add:aString.
   1.752 +    watchingTranslationEditor notNil ifTrue:[
   1.753 +        watchingTranslationEditor recordNewTranslation:aString.
   1.754 +    ].
   1.755 +    ^ realResourcePack perform:(thisContext sender selector) withArguments:(thisContext sender args).
   1.756 +!
   1.757 +
   1.758 +string:aString
   1.759 +    ^ self forwardFor:aString
   1.760  ! !
   1.761  
   1.762  !InternationalLanguageTranslationEditor::KeyStringsToLanguageMappings class methodsFor:'instance creation'!