[squeak-dev] Squeak 4.5: GetText-nice.34.mcz
commits at source.squeak.org
commits at source.squeak.org
Fri Jan 24 20:02:03 UTC 2014
Chris Muller uploaded a new version of GetText to project Squeak 4.5:
http://source.squeak.org/squeak45/GetText-nice.34.mcz
==================== Summary ====================
Name: GetText-nice.34
Author: nice
Time: 25 December 2013, 11:02:39.404 pm
UUID: 4d432f8e-55be-428a-9138-63dd1738035e
Ancestors: GetText-fbs.33
Change a few print:(aFloat roundTo: 0.01) into nextPutAll:(aFloat printShowingMaxDecimalPlaces: 2)
==================== Snapshot ====================
SystemOrganization addCategory: #'GetText-Editor'!
Object subclass: #GetTextExporter
instanceVariableNames: 'stream'
classVariableNames: ''
poolDictionaries: ''
category: 'GetText-Editor'!
!GetTextExporter commentStamp: '<historical>' prior: 0!
Export translations to gettext format divided into categories.
"Export gettext template files"
GetTextExporter new exportTemplate.
"Export translation files for current locale"
GetTextExporter new exportTranslator: (InternalTranslator newLocaleID: LocaleID current).
"Export all gettext template and po files."
GetTextExporter exportAll.
!
----- Method: GetTextExporter class>>coverageStatus (in category 'utilities') -----
coverageStatus
"self coverageStatus"
| keys diff |
keys := self keys.
diff := InternalTranslator allKnownPhrases keys difference: keys.
Transcript cr; show: 'Detected keywords by GetTextExporter2: ' , keys size printString.
Transcript cr; show: 'All known phrases in InternalTranslator: ' , InternalTranslator allKnownPhrases size printString.
Transcript cr; show: 'Coverage: ' , (keys size / InternalTranslator allKnownPhrases size * 100.0) printString , '%'.
diff inspect!
----- Method: GetTextExporter class>>exportAll (in category 'utilities') -----
exportAll
"GetTextExporter2 exportAll"
self new exportTemplate.
InternalTranslator availableLanguageLocaleIDs
do: [:each | self new exportTranslator: each translator]!
----- Method: GetTextExporter class>>exportTemplate (in category 'utilities') -----
exportTemplate
"GetTextExporter2 exportTemplate"
self new exportTemplate.!
----- Method: GetTextExporter class>>keys (in category 'utilities') -----
keys
| categories |
categories := Dictionary new.
self new appendTranslations: categories.
^ categories values
inject: Set new
into: [:set :next | set addAll: next keys;
yourself]!
----- Method: GetTextExporter class>>listAllHelp (in category 'utilities') -----
listAllHelp
"self listAllHelp"
| spec specs oCatalog flap flapSelectors allKeys oCatalogHelp flapHelp |
oCatalog := Dictionary new.
Morph withAllSubclasses
do: [:aClass | (aClass class includesSelector: #descriptionForPartsBin)
ifTrue: [spec := aClass descriptionForPartsBin.
oCatalog at: spec formalName put: spec documentation]].
Morph withAllSubclasses
do: [:aClass | (aClass class includesSelector: #supplementaryPartsDescriptions)
ifTrue: [specs := aClass supplementaryPartsDescriptions.
specs
do: [:each | oCatalog at: each formalName put: each documentation]]].
flap := Dictionary new.
flapSelectors := #(#defaultsQuadsDefiningPlugInSuppliesFlap #defaultsQuadsDefiningStackToolsFlap #defaultsQuadsDefiningSuppliesFlap #defaultsQuadsDefiningToolsFlap #defaultsQuadsDefiningWidgetsFlap #defaultsQuadsDefiningScriptingFlap ).
flapSelectors
do: [:selector |
specs := Flaps perform: selector.
specs
do: [:each | flap at: each third put: each fourth]].
allKeys := oCatalog keys intersection: flap keys.
allKeys asArray sort
do: [:each |
oCatalogHelp := oCatalog
at: each
ifAbsent: [''].
flapHelp := flap
at: each
ifAbsent: [''].
oCatalogHelp = flapHelp
ifFalse: [Transcript cr; show: 'Name: ' , each.
Transcript cr; show: 'O: ' , oCatalogHelp.
Transcript cr; show: 'F: ' , flapHelp.
Transcript cr.
]]!
----- Method: GetTextExporter class>>verifyExport (in category 'utilities') -----
verifyExport
"Same as #verifyMsgID: but it writes / reads .po files actually"
"GetTextExporter2 verifyExport"
"InternalTranslator removeLocaleID: (LocaleID isoString: 'test-US')"
| src dst localeID |
localeID := LocaleID isoString: 'test-US'.
self verifyMsgID: localeID.
src := localeID translator.
self new exportTranslator: src.
InternalTranslator removeLocaleID: localeID.
dst := localeID translator.
GetTextImporter import: dst allDirectory: FileDirectory default!
----- Method: GetTextExporter class>>verifyMsgID: (in category 'utilities') -----
verifyMsgID: localeID
"GetTextExporter2 verifyMsgID: (LocaleID isoString: 'test-US')"
"InternalTranslator removeLocaleID: (LocaleID isoString: 'test-US')"
"Test gettext keyword extract function without file I/O.
A language named <langName> will be made. And
all possible translated words are shown with extra X charactor like
'XwordX' in the language."
| src |
InternalTranslator removeLocaleID: localeID.
src := localeID translator.
self keys
do: [:key | src generics at: key put: 'X' , key , 'X']!
----- Method: GetTextExporter>>appendStringReceivers:into: (in category 'private') -----
appendStringReceivers: aSymbol into: domains
| literals references domainName methodReference keywords found |
found := TranslatedReceiverFinder new stringReceiversWithContext: aSymbol.
found do: [ :assoc |
methodReference := assoc key.
keywords := assoc value.
domainName := (PackageOrganizer default packageOfMethod: methodReference ifNone: [nil]).
domainName := domainName isNil ifTrue: [TextDomainManager defaultDomain] ifFalse: [domainName name].
literals := domains at: domainName ifAbsentPut: [Dictionary new].
keywords do: [ :literal |
references := literals at: literal ifAbsentPut: [OrderedCollection new].
references add: methodReference.
].
].
!
----- Method: GetTextExporter>>appendTranslations: (in category 'exporting') -----
appendTranslations: domains
self appendStringReceivers: #translated into: domains.
self appendStringReceivers: #translatedNoop into: domains.
self appendVocabularies: domains.
!
----- Method: GetTextExporter>>appendVocabularies: (in category 'private') -----
appendVocabularies: domains
| literalsForDomain references domainName methodReference |
EToyVocabulary allPhrasesWithContextToTranslate do: [ :r |
methodReference := (MethodReference class: (r second) selector: (r third)).
"domainName := self getTextDomainForPackage: (PackageOrganizer default packageOfMethod: methodReference)".
domainName := 'Etoys-Tiles'.
literalsForDomain := domains at: domainName ifAbsentPut: [Dictionary new].
r fourth do: [ :literal |
references := literalsForDomain at: literal ifAbsentPut: [OrderedCollection new].
references add: methodReference.
].
].
!
----- Method: GetTextExporter>>createExtraInformation (in category 'private') -----
createExtraInformation
| extras |
extras := OrderedCollection new.
#(
'Language name as you''d like it to appear in the Languages menu' 'Language-Name'
'Directionality of language' 'Language-Direction'
) pairsDo: [:first :second |
extras add: (Array with: '' with: first with: second).
].
^ extras!
----- Method: GetTextExporter>>createHeaders (in category 'private-headers') -----
createHeaders
| headers |
headers := OrderedCollection new.
headers add: 'Project-Id-Version' -> 'eToys'.
headers add: 'POT-Creation-Date' -> self currentDateAndTime.
headers add: 'PO-Revision-Date' -> self currentDateAndTime.
headers add: 'Last-Translator' -> ''.
headers add: 'Language-Team' -> ''.
headers add: 'MIME-Version' -> '1.0'.
headers add: 'Content-Type' -> ('text/plain; charset=', stream converter class encodingNames first).
headers add: 'Content-Transfer-Encoding' -> '8bit'.
^ headers!
----- Method: GetTextExporter>>currentDateAndTime (in category 'private') -----
currentDateAndTime
^ String
streamContents: [:aStream |
aStream nextPutAll: Date today yyyymmdd;
space.
Time now
print24: true
showSeconds: false
on: aStream.
aStream nextPutAll: '-0000']!
----- Method: GetTextExporter>>dirNameCategory:translator: (in category 'exporting') -----
dirNameCategory: category translator: translator
"Answer a file name for the category. Make one if it is not exist yet.
Make template file name if translator is nil"
"self new dirNameCategory: 'Morphic-Scripting Support' translator:
NaturalLanguageTranslator current"
"self new dirNameCategory: 'Morphic-Scripting Support' translator: nil"
| safeCategory fileName dirName pathName |
safeCategory := category copyReplaceAll: ' ' with: ':='.
fileName := translator
ifNil: [safeCategory , '.pot']
ifNotNil: [translator localeID posixName , '.po'].
dirName := (safeCategory findTokens: '-')
inject: 'po'
into: [:aString :next | aString , FileDirectory slash , next].
pathName := dirName , FileDirectory slash , fileName.
(FileDirectory default directoryNamed: dirName) assureExistence.
^ pathName!
----- Method: GetTextExporter>>dirNameDomain:translator: (in category 'exporting') -----
dirNameDomain: domain translator: translator
"Answer a file name for the domain. Make one if it is not exist yet.
Make template file name if translator is nil"
"self new dirNameDomain: 'etoys' translator:
NaturalLanguageTranslator current"
"self new dirNameDomain: 'etoys' translator: nil"
| fileName dirName pathName |
"safeCategory := category copyReplaceAll: ' ' with: ':='."
fileName := domain,
(translator
ifNil: ['.pot']
ifNotNil: ['.po']).
dirName := 'po', FileDirectory slash,
(translator
ifNil: ['templates']
ifNotNil: [translator localeID posixName]).
pathName := dirName , FileDirectory slash , fileName.
(FileDirectory default directoryNamed: dirName) assureExistence.
^ pathName!
----- Method: GetTextExporter>>export:translator:domain: (in category 'private') -----
export: literals translator: translator domain: domainName
| fileName |
"Export a gettext file in a category. literals is a dictionary of keyword -> #(MethodReference...) in the textDomain."
fileName := self dirNameDomain: domainName translator: translator.
[stream := FileStream forceNewFileNamed: fileName.
stream lineEndConvention: #lf.
stream converter: UTF8TextConverter new.
self exportHeader: domainName.
domainName = TextDomainManager defaultDomain
ifTrue: [self exportInformation: self createExtraInformation].
self exportBody: literals translator: translator]
ensure: [stream close]!
----- Method: GetTextExporter>>exportBody:translator: (in category 'file out') -----
exportBody: literals translator: translator
"Export a gettext file body. literals is a dictionary of keyword ->
#(MethodReference...) in the textDomain."
"Build {sortKey. comment. msgid } to optimize sorting (getting category is
too slow).
If there are two or more methods for a mgsid, only first method
(alphabetical) is used for sorting."
| sorted msgid sortedMethods category sortKey comment triplets commentUnderLined |
triplets := literals associations
collect: [:assoc |
msgid := assoc key.
sortedMethods := assoc value asArray sort.
category := (Smalltalk at: sortedMethods first classSymbol) category asString.
sortKey := category , ',' , sortedMethods first printString , ',' , msgid.
comment := (sortedMethods
collect: [:each | each actualClass asString , '>>' , each methodSymbol asString])
inject: category
into: [:result :methodName | result , ',' , methodName].
"Replace white spaces to := because gettext tool might
replace a space to a new line some times, and it makes
difficult to take a diff."
commentUnderLined := comment copyReplaceAll: ' ' with: ':='.
Array
with: sortKey
with: commentUnderLined
with: msgid].
"Sort and output the words"
sorted := triplets
sort: [:a :b | a first <= b first].
sorted
do: [:triplet |
comment := triplet second.
msgid := triplet third.
self exportRecordHeader: comment.
self
exportPhrase: msgid
translation: (self translationFor: msgid in: translator)]!
----- Method: GetTextExporter>>exportHeader (in category 'private-headers') -----
exportHeader
self exportTag: 'msgid' msg: ''.
self exportTag: 'msgstr' msg: ''.
self createHeaders
do: [:each | self exportHeaderLineKey: each key value: each value].
stream cr; cr!
----- Method: GetTextExporter>>exportHeader: (in category 'private') -----
exportHeader: domainName
| headers |
self exportTag: 'msgid' msg: ''.
self exportTag: 'msgstr' msg: ''.
headers := self createHeaders.
headers add: 'X-Etoys-Domain' -> domainName.
headers do: [:each | self exportHeaderLineKey: each key value: each value].
stream cr; cr!
----- Method: GetTextExporter>>exportHeaderLineKey:value: (in category 'private') -----
exportHeaderLineKey: keyString value: valueString
stream nextPut: $";
nextPutAll: keyString;
nextPut: $:;
space;
nextPutAll: valueString;
nextPutAll: '\n';
nextPut: $";
cr.!
----- Method: GetTextExporter>>exportInformation: (in category 'private') -----
exportInformation: anOrderedCollection
anOrderedCollection do: [:each |
self exportRecordHeader: each second.
self exportPhrase: each third translation: ''].
stream cr.!
----- Method: GetTextExporter>>exportPhrase:translation: (in category 'private') -----
exportPhrase: phraseString translation: translationString
| normalizedTrans tmp transStartsWithCR transEndsWithCR|
phraseString isEmpty
ifTrue: [^ self].
self exportTag: 'msgid' msg: phraseString.
translationString size = 0 ifTrue: [
normalizedTrans := ''
] ifFalse: [
transEndsWithCR := translationString last = (Character cr).
phraseString last = (Character cr) ifTrue: [
transEndsWithCR ifTrue: [
normalizedTrans := translationString
] ifFalse: [
normalizedTrans := translationString , String cr
]
] ifFalse: [
transEndsWithCR ifTrue: [
normalizedTrans := translationString allButLast
] ifFalse: [
normalizedTrans := translationString
]
].
transStartsWithCR := normalizedTrans first = (Character cr).
phraseString first = (Character cr) ifTrue: [
transStartsWithCR ifFalse: [
tmp := (Character cr asString) , normalizedTrans.
normalizedTrans := tmp.
]
] ifFalse: [
transStartsWithCR ifTrue: [
normalizedTrans := normalizedTrans allButFirst
]
]
].
self exportTag: 'msgstr' msg: normalizedTrans.
stream cr!
----- Method: GetTextExporter>>exportRecordHeader: (in category 'private') -----
exportRecordHeader: context
stream
nextPutAll: '#: ';
nextPutAll: context;
cr.!
----- Method: GetTextExporter>>exportTag:msg: (in category 'private') -----
exportTag: tag msg: aString
stream nextPutAll: tag.
stream space.
aString lineIndicesDo: [:start :endWithoutDelimiters :end |
| line |
line := (end = endWithoutDelimiters)
ifTrue: [aString copyFrom: start to: endWithoutDelimiters]
ifFalse: [(aString at: endWithoutDelimiters + 1) = Character cr
ifTrue: [aString copyFrom: start to: endWithoutDelimiters + 1]
ifFalse: [(aString copyFrom: start to: endWithoutDelimiters) copyWith: Character cr]].
stream
nextPut: $";
nextPutAll: (self formatString: line);
nextPut: $";
cr].!
----- Method: GetTextExporter>>exportTemplate (in category 'exporting') -----
exportTemplate
"GetTextExporter2 new exportTemplate"
self exportTranslator: nil!
----- Method: GetTextExporter>>exportTranslator: (in category 'exporting') -----
exportTranslator: translator
"Export translation files. the file extention is 'po', or 'pot' if translator is nil "
"GetTextExporter2 new exportTranslator: NaturalLanguageTranslator current "
| domains |
domains := Dictionary new.
self appendTranslations: domains.
domains
keysAndValuesDo: [:domainName :value |
self
export: value
translator: translator
domain: domainName]!
----- Method: GetTextExporter>>formatReplacements (in category 'private') -----
formatReplacements
| replacements |
replacements := OrderedCollection new.
replacements add: '\' -> '\\'.
replacements add: String cr -> '\n'.
replacements add: String tab -> '\t'.
replacements add: '"' -> '\"'.
^ replacements!
----- Method: GetTextExporter>>formatString: (in category 'private') -----
formatString: aString
| result |
result := aString.
self formatReplacements
do: [:each | result := result copyReplaceAll: each key with: each value].
^ result!
----- Method: GetTextExporter>>getTextDomainForPackage: (in category 'as yet unclassified') -----
getTextDomainForPackage: aPackageInfo
^TextDomainManager domainForPackage: aPackageInfo!
----- Method: GetTextExporter>>stream (in category 'accessing') -----
stream
^ stream!
----- Method: GetTextExporter>>stream: (in category 'accessing') -----
stream: aStream
stream := aStream!
----- Method: GetTextExporter>>translationFor:in: (in category 'private') -----
translationFor: aKey in: translator
| translation |
translator ifNil: [^ ''].
TextDomainManager allKnownDomains do: [:domain |
translation := translator translate: aKey inDomain: domain.
aKey = translation ifFalse: [^translation]
].
^ aKey!
Object subclass: #GetTextInterchange
instanceVariableNames: 'language stream'
classVariableNames: ''
poolDictionaries: ''
category: 'GetText-Editor'!
GetTextInterchange subclass: #GetTextImporter
instanceVariableNames: 'msgId msgStr state'
classVariableNames: ''
poolDictionaries: ''
category: 'GetText-Editor'!
!GetTextImporter commentStamp: 'tak 10/24/2007 11:23' prior: 0!
GetTextImporter load gettext po file into a InternalTranslator.
GetTextImporter new importID: (LocaleID isoString: 'lang-name') fileNamed: 'lang.po'
!
----- Method: GetTextImporter class>>cleanUpUnnecessaryPhrases (in category 'utilities') -----
cleanUpUnnecessaryPhrases
| keys refuse replaceBlock reader writer char result |
"GetTextImporter cleanUpUnnecessaryPhrases"
""
"Collect wrong phrases"
keys := InternalTranslator allKnownPhrases copy keys.
refuse := Set new.
"replaceBlock value: 'te\\nst'."
replaceBlock := [:aString |
reader := aString readStream.
writer := '' writeStream.
[reader atEnd]
whileFalse: [char := reader next.
(char = $\
and: [reader peek = $\])
ifFalse: [writer nextPut: char]].
writer contents].
keys
do: [:each |
result := replaceBlock value: each.
(result ~= each
and: [keys includes: result])
ifTrue: [refuse add: each].
result := GetTextImporter new formatString: each.
(result ~= each
and: [keys includes: result])
ifTrue: [refuse add: each]].
""
"Remove from translated"
InternalTranslator cachedTranslations
do: [:each | refuse
do: [:key | each translations
removeKey: key
ifAbsent: []]].
""
"Remove from untranslated"
refuse
do: [:key | InternalTranslator allKnownPhrases
removeKey: key
ifAbsent: []]!
----- Method: GetTextImporter class>>import:allDirectory: (in category 'utilities') -----
import: translator allDirectory: aFileDirectory
"self import: NaturalLanguageTranslator current allDirectory:
FileDirectory default"
| fileName targetFile |
fileName := translator localeID posixName , '.po'.
(FileDirectory default directoryNamed: 'po')
withAllSubdirectoriesCollect: [:each | (each fileExists: fileName)
ifTrue: [targetFile := each fullNameFor: fileName.
self new import: translator fileNamed: targetFile]]!
----- Method: GetTextImporter class>>importAll (in category 'utilities') -----
importAll
"GetTextImporter importAll"
"Import all gettext files on po/. Only registered language is imported"
InternalTranslator cachedTranslations
do: [:translator | self import: translator allDirectory: FileDirectory default]!
----- Method: GetTextImporter>>appendId: (in category 'parsing') -----
appendId: aString
msgId := msgId , aString!
----- Method: GetTextImporter>>appendStr: (in category 'parsing') -----
appendStr: aString
msgStr := msgStr , aString!
----- Method: GetTextImporter>>formatString: (in category 'private') -----
formatString: aString
"
self assert: (GetTextImporter new formatString: 'test') = 'test'.
self assert: (GetTextImporter new formatString: 'te\nst') = ('te', String cr, 'st').
self assert: (GetTextImporter new formatString: 'te\\nst') = ('te\nst').
self assert: (GetTextImporter new formatString: 'te\\st') = ('te\st').
self assert: (GetTextImporter new formatString: 'te\st') = ('te\st').
"
| reader writer char |
reader := aString readStream.
writer := '' writeStream.
[reader atEnd]
whileFalse: [char := reader next.
(char = $\
and: [reader atEnd not])
ifTrue: [char := reader next.
char caseOf: {
[$n] -> [writer nextPut: Character cr].
[$t] -> [writer nextPut: Character tab].
[$"] -> [writer nextPut: $"].
[$\] -> [writer nextPut: $\]}
otherwise: [writer nextPutAll: {$\. char}]]
ifFalse: [writer nextPut: char]].
^ writer contents!
----- Method: GetTextImporter>>import: (in category 'importing') -----
import: aLanguage
^ self import: aLanguage fileNamed: aLanguage localeID posixName , '.po'!
----- Method: GetTextImporter>>import:fileNamed: (in category 'importing') -----
import: aLanguage fileNamed: fileName
self importID: aLanguage localeID fileNamed: fileName!
----- Method: GetTextImporter>>importID:fileNamed: (in category 'importing') -----
importID: localeID fileNamed: fileName
| currentPlatform |
language := InternalTranslator newLocaleID: localeID.
currentPlatform := Locale currentPlatform.
[Locale
currentPlatform: (Locale localeID: localeID).
[stream := FileStream readOnlyFileNamed: fileName.
stream text.
self parse]
ensure: [stream notNil
ifTrue: [stream close]]]
ensure: [Locale currentPlatform: currentPlatform].
NaturalLanguageTranslator privateStartUp "Actually it is not private no more...".!
----- Method: GetTextImporter>>initialize (in category 'initialize-release') -----
initialize
msgId := ''.
msgStr := ''.
state := nil!
----- Method: GetTextImporter>>parse (in category 'parsing') -----
parse
| size |
size := (stream isKindOf: FileStream)
ifTrue: [stream size]
ifFalse: [1].
ProgressInitiationException
display: 'Importing phrases from a gettext file.'
during: [:bar | [stream atEnd]
whileFalse: [| line |
line := stream upTo: Character linefeed.
self
parseLine: ((line endsWith: String cr)
ifTrue: [line allButLast]
ifFalse: [line]).
bar value: stream position / size]].
self storeTranslation!
----- Method: GetTextImporter>>parseLine: (in category 'parsing') -----
parseLine: lineString
(lineString beginsWith: '"Content-Type:')
ifTrue: [self setContentType: lineString.
^ self].
(lineString beginsWith: '#')
ifTrue: ["do nothing"
^ self].
lineString = ''
ifTrue: [^ self storeTranslation].
(lineString beginsWith: 'msgid')
ifTrue: [state := #appendId:.
self parseMsg: lineString.
^ self].
(lineString beginsWith: 'msgstr')
ifTrue: [state := #appendStr:.
self parseMsg: lineString.
^ self].
self parseMsg: lineString!
----- Method: GetTextImporter>>parseMsg: (in category 'parsing') -----
parseMsg: lineString
| begin end msg |
begin := lineString indexOf: $".
end := lineString lastIndexOf: $".
msg := begin + 1 <= (end - 1)
ifTrue: [lineString copyFrom: begin + 1 to: end - 1]
ifFalse: [''].
state
ifNotNil: [self perform: state with: msg].
^ msg!
----- Method: GetTextImporter>>setContentType: (in category 'parsing') -----
setContentType: lineString
"self new setContentType: 'Content-Type: text/plain; charset=utf-8'"
| reader charSet |
reader := lineString readStream.
reader upTo: $=.
charSet := reader upTo: $\.
stream
converter: (TextConverter newForEncoding: charSet)!
----- Method: GetTextImporter>>storeTranslation (in category 'parsing') -----
storeTranslation
| key |
key := self formatString: msgId.
msgId isEmpty
ifFalse: [InternalTranslator registerPhrase: key.
msgStr isEmpty
ifFalse: [language
rawPhrase: key
translation: (self formatString: msgStr)]].
self initialize!
----- Method: GetTextInterchange>>defaultFileName (in category 'private') -----
defaultFileName
^ language localeID posixName , '.po'!
----- Method: GetTextInterchange>>language: (in category 'accessing') -----
language: translator
language := translator!
----- Method: GetTextInterchange>>stream (in category 'accessing') -----
stream
^ stream!
----- Method: GetTextInterchange>>stream: (in category 'accessing') -----
stream: aStream
stream := aStream!
SystemWindow subclass: #LanguageEditor
instanceVariableNames: 'translator translations untranslated selectedTranslation selectedTranslations selectedUntranslated translationsList untranslatedList translationText translationsFilter untranslatedFilter newerKeys'
classVariableNames: 'CheckMethods'
poolDictionaries: ''
category: 'GetText-Editor'!
!LanguageEditor commentStamp: 'dgd 11/16/2003 15:02' prior: 0!
Editor for Babel's languages.
Open it from
World Menu >> open... >> Language Editor (to open on default language)
World Menu >> open... >> Language Editor for... (to choose the language)
Or click:
LanguageEditor openOnDefault.
LanguageEditor open.
See http://swiki.agro.uba.ar/small_land/191 for documentation
!
----- Method: LanguageEditor class>>checkMethods (in category 'private') -----
checkMethods
^CheckMethods ifNil: [CheckMethods := self initCheckMethods]!
----- Method: LanguageEditor class>>ensureVisibilityOfWindow: (in category 'private') -----
ensureVisibilityOfWindow: aWindow
"private - activate the window"
| |
aWindow expand.
aWindow comeToFront.
""
aWindow
right: (aWindow right min: World right).
aWindow
bottom: (aWindow bottom min: World bottom).
aWindow
left: (aWindow left max: World left).
aWindow
top: (aWindow top max: World top).
""
aWindow flash; flash!
----- Method: LanguageEditor class>>initCheckMethods (in category 'initialize-release') -----
initCheckMethods
"LanguageEditor initCheckMethods"
| registry |
registry := Dictionary new.
registry
at: 'es' put: #checkSpanishPhrase:translation:;
yourself.
^registry!
----- Method: LanguageEditor class>>initialize (in category 'initialize-release') -----
initialize
"initialize the receiver"
(TheWorldMenu respondsTo: #registerOpenCommand:)
ifTrue: [""
TheWorldMenu registerOpenCommand: {'Language Editor' translated. {self. #openOnDefault}}.
TheWorldMenu registerOpenCommand: {'Language Editor for...' translated. {self. #open}}]!
----- Method: LanguageEditor class>>on: (in category 'instance creation') -----
on: localeID
"answer an instance of the receiver on aLanguage"
^ self new
initializeOn: (InternalTranslator cachedTranslations
at: localeID
ifAbsent: [self
error: ('Translator for {1} is not found' translated format: {localeID})])!
----- Method: LanguageEditor class>>open (in category 'opening') -----
open
"open the receiver on any language"
"
LanguageEditor open.
"
| menu |
menu := MenuMorph new defaultTarget: self.
menu addTitle: 'Language Editor for...' translated.
""
(InternalTranslator availableLanguageLocaleIDs
asSortedCollection: [:x :y | x asString <= y asString])
do: [:eachLanguage | ""
menu
add: eachLanguage name
target: self
selector: #openOn:
argument: eachLanguage].
""
menu popUpInWorld!
----- Method: LanguageEditor class>>openOn: (in category 'instance creation') -----
openOn: aLanguage
"open an instance on aLanguage"
World submorphs
do: [:each | ""
((each isKindOf: LanguageEditor)
and: [each translator == aLanguage])
ifTrue: [""
self ensureVisibilityOfWindow: each.
^ self]].
""
^ (self on: aLanguage) openInWorld!
----- Method: LanguageEditor class>>openOnDefault (in category 'opening') -----
openOnDefault
"open the receiver on the default language"
self openOn: LocaleID current!
----- Method: LanguageEditor class>>unload (in category 'initialize-release') -----
unload
"the receiver is being unloaded"
(TheWorldMenu respondsTo: #registerOpenCommand:)
ifTrue: [""
TheWorldMenu unregisterOpenCommand: 'Language Editor'.
TheWorldMenu unregisterOpenCommand: 'Language Editor for...'] !
----- Method: LanguageEditor>>addTranslation (in category 'gui methods') -----
addTranslation
"translate a phrase"
| phrase |
phrase := UIManager default
request: 'enter the original:' translated
initialAnswer: ''.
(phrase isNil
or: [phrase = ''])
ifTrue: [
self beep.
^ self].
self translatePhrase: phrase!
----- Method: LanguageEditor>>applyTranslations (in category 'gui methods') -----
applyTranslations
"private - try to apply the translations as much as possible all
over the image"
Project current updateLocaleDependents!
----- Method: LanguageEditor>>asHtml: (in category 'reporting') -----
asHtml: aString
| stream |
stream := String new writeStream.
aString
do: [:each |
each caseOf: {
[Character cr] -> [stream nextPutAll: '<br>'].
[$&] -> [stream nextPutAll: '&'].
[$<] -> [stream nextPutAll: '<'].
[$>] -> [stream nextPutAll: '>'].
[$*] -> [stream nextPutAll: '☆'].
[$@] -> [stream nextPutAll: '&at;']}
otherwise: [stream nextPut: each]].
^ stream contents!
----- Method: LanguageEditor>>browseMethodsWithTranslation (in category 'gui methods') -----
browseMethodsWithTranslation
| translation |
self selectedTranslation isZero
ifTrue: [""
self beep.
self inform: 'select the translation to look for' translated.
^ self].
""
translation := self translations at: self selectedTranslation.
self systemNavigation browseMethodsWithLiteral: translation!
----- Method: LanguageEditor>>browseMethodsWithUntranslated (in category 'gui methods') -----
browseMethodsWithUntranslated
| untrans |
self selectedUntranslated isZero
ifTrue: [""
self beep.
self inform: 'select the untrans phrase to look for' translated.
^ self].
""
untrans := self untranslated at: self selectedUntranslated.
SystemNavigation default browseMethodsWithLiteral: untrans.
!
----- Method: LanguageEditor>>check (in category 'private') -----
check
"check the translations and answer a collection with the results"
| results counter phrasesCount checkMethod |
results := OrderedCollection new.
untranslated := self untranslated.
phrasesCount := self translations size + self untranslated size.
counter := 0.
checkMethod := self class checkMethods at: self translator localeID printString ifAbsent: [^results].
self translations
keysAndValuesDo: [:phrase :translation |
| result |
result := self perform: checkMethod with: phrase with: translation.
(result notNil
and: [result notEmpty])
ifTrue: [results add: {phrase. translation. result}].
counter := counter + 1.
(counter isDivisibleBy: 50)
ifTrue: [| percent |
percent := counter / phrasesCount * 100 printShowingMaxDecimalPlaces: 2.
Transcript
show: ('- checked {1} phrases of {2} ({3}%)...' translated format: {counter. phrasesCount. percent});
cr]].
self untranslated
do: [:phrase |
| result |
result := self checkUntranslatedPhrase: phrase.
(result notNil
and: [result notEmpty])
ifTrue: [results add: {phrase. nil. result}].
counter := counter + 1.
(counter isDivisibleBy: 50)
ifTrue: [| percent |
percent := counter / phrasesCount * 100 printShowingMaxDecimalPlaces: 2.
Transcript
show: ('- checked {1} phrases of {2} ({3}%)...' translated format: {counter. phrasesCount. percent});
cr]].
^ results!
----- Method: LanguageEditor>>checkPhrase:translation: (in category 'private') -----
checkPhrase: phraseString translation: translationString
^nil!
----- Method: LanguageEditor>>checkSpanishPhrase:translation: (in category 'private') -----
checkSpanishPhrase: phraseString translation: translationString
"check the translation and aswer a string with a comment or a
nil meaning no-comments"
| superResult |
superResult := self checkPhrase: phraseString translation: translationString.
superResult isNil
ifFalse: [^ superResult].
"For some reason, MCInstaller couldn't read Spanish character. "
"((translationString includes: $?)
and: [(translationString includes: $ø) not])
ifTrue: [^ 'øOlvidÛ el signo de pregunta?'].
((translationString includes: $!!)
and: [(translationString includes: $°) not])
ifTrue: [^ 'øOlvidÛ el signo de admiraciÛn?'].
"
^ nil
!
----- Method: LanguageEditor>>checkUntranslatedPhrase: (in category 'private') -----
checkUntranslatedPhrase: phraseString
"check the phrase an aswer a string with a comment or a nil
meaning no-comments"
(self translations includes: phraseString)
ifTrue: [^ 'possible double-translation' translated].
^ nil!
----- Method: LanguageEditor>>codeSelectedTranslation (in category 'gui methods') -----
codeSelectedTranslation
| keys code |
keys := selectedTranslations
collect: [:key | self translations at: key].
code := String
streamContents: [:aStream | self translator fileOutOn: aStream keys: keys withBOM: false].
(StringHolder new contents: code)
openLabel: 'exported codes' translated!
----- Method: LanguageEditor>>codeSelectedTranslationAsMimeString (in category 'gui methods') -----
codeSelectedTranslationAsMimeString
| keys code tmpStream s2 gzs cont |
keys := selectedTranslations
collect: [:key | self translations at: key].
code := String
streamContents: [:aStream | self translator fileOutOn: aStream keys: keys withBOM: false].
tmpStream := MultiByteBinaryOrTextStream on: ''.
tmpStream converter: UTF8TextConverter new.
tmpStream nextPutAll: code.
s2 := RWBinaryOrTextStream on: ''.
gzs := GZipWriteStream on: s2.
tmpStream reset.
gzs nextPutAll: (tmpStream binary contentsOfEntireFile asString) contents.
gzs close.
s2 reset.
cont := String streamContents: [:strm |
strm nextPutAll: '"Gzip+Base64 encoded translation for;'; cr.
strm nextPutAll: '#('.
keys do: [:each | strm nextPutAll: '''', each, ''' '.].
strm nextPutAll: ')"'; cr; cr.
strm nextPutAll: 'NaturalLanguageTranslator loadForLocaleIsoString: '.
strm nextPut: $'.
strm nextPutAll: translator localeID isoString.
strm nextPut: $'.
strm nextPutAll: ' fromGzippedMimeLiteral: '.
strm nextPut: $'.
strm nextPutAll: (Base64MimeConverter mimeEncode: s2) contents.
strm nextPutAll: '''.'.
strm cr.
].
(StringHolder new contents: cont)
openLabel: 'exported codes in Gzip+Base64 encoding' translated!
----- Method: LanguageEditor>>createButtonLabel:action:help: (in category 'initialization - toolbar') -----
createButtonLabel: aString action: actionSelector help: helpString
"create a toolbar for the receiver"
| button |
button := SimpleButtonMorph new target: self;
label: aString translated "font: Preferences standardButtonFont";
actionSelector: actionSelector;
setBalloonText: helpString translated;
color: translator defaultBackgroundColor twiceDarker;
borderWidth: 2;
borderColor: #raised.
""
^ button!
----- Method: LanguageEditor>>createMainToolbar (in category 'initialization - toolbar') -----
createMainToolbar
"create a toolbar for the receiver"
| toolbar |
toolbar := self createRow.
""
" toolbar
addMorphBack: (self
createUpdatingButtonWording: #debugWording
action: #switchDebug
help: 'Switch the debug flag')."
toolbar addTransparentSpacerOfSize: 5 @ 0.
""
toolbar
addMorphBack: (self
createButtonLabel: 'new'
action: #newTranslations
help: 'Create translations for new language.').
toolbar
addMorphBack: (self
createButtonLabel: 'save'
action: #saveToFile
help: 'Save the translations to a file').
toolbar
addMorphBack: (self
createButtonLabel: 'load'
action: #loadFromFile
help: 'Load the translations from a file').
toolbar
addMorphBack: (self
createButtonLabel: 'merge'
action: #mergeFromFile
help: 'Merge the current translations with the translations in a file').
""
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'apply'
action: #applyTranslations
help: 'Apply the translations as much as possible.').
""
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'check translations'
action: #check
help: 'Check the translations and report the results.').
toolbar
addMorphBack: (self
createButtonLabel: 'report'
action: #report
help: 'Create a report.').
toolbar
addMorphBack: (self
createButtonLabel: 'gettext'
action: #getText
help: 'Interface with gettext.').
""
^ toolbar!
----- Method: LanguageEditor>>createRow (in category 'initialization - toolbar') -----
createRow
"create a row"
| row |
row := AlignmentMorph newRow.
row layoutInset: 3;
wrapCentering: #center;
cellPositioning: #leftCenter.
""
^ row!
----- Method: LanguageEditor>>createStatusbar (in category 'initialization - statusbar') -----
createStatusbar
"create the statusbar for the receiver"
| statusbar |
statusbar := self createRow.
statusbar addMorph: ((UpdatingStringMorph on: self selector: #status) growable: true;
useStringFormat;
hResizing: #spaceFill;
stepTime: 2000).
^ statusbar!
----- Method: LanguageEditor>>createTranslationsToolbar (in category 'initialization - toolbar') -----
createTranslationsToolbar
"create a toolbar for the receiver"
| toolbar |
toolbar := self createRow.
""
toolbar
addMorphBack: (self
createUpdatingButtonWording: #translationsFilterWording
action: #filterTranslations
help: 'Filter the translations list.').
toolbar addTransparentSpacerOfSize: 5 @ 0.
""
toolbar
addMorphBack: (self
createButtonLabel: 'search'
action: #searchTranslation
help: 'Search for a translation containing...').
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'remove'
action: #removeTranslation
help: 'Remove the selected translation. If none is selected, ask for the one to remove.').
""
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'where'
action: #browseMethodsWithTranslation
help: 'Launch a browser on all methods that contain the phrase as a substring of any literal String.').
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'r-unused'
action: #removeTranslatedButUnusedStrings
help: 'Remove all the strings that are not used by the system').
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'add '
action: #addTranslation
help: 'Add a new phrase').
^ toolbar!
----- Method: LanguageEditor>>createUntranslatedToolbar (in category 'initialization - toolbar') -----
createUntranslatedToolbar
"create a toolbar for the receiver"
| toolbar |
toolbar := self createRow.
""
toolbar
addMorphBack: (self
createUpdatingButtonWording: #untranslatedFilterWording
action: #filterUntranslated
help: 'Filter the untranslated list.').
toolbar addTransparentSpacerOfSize: 5 @ 0.
""
toolbar
addMorphBack: (self
createButtonLabel: 'search'
action: #searchUntranslated
help: 'Search for a untranslated phrase containing...').
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'remove'
action: #removeUntranslated
help: 'Remove the selected untranslated phrease. If none is selected, ask for the one to remove.').
""
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'translate'
action: #translate
help: 'Translate the selected untranslated phrase or a new phrase').
""
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'where'
action: #browseMethodsWithUntranslated
help: 'Launch a browser on all methods that contain the phrase as a substring of any literal String.').
toolbar addTransparentSpacerOfSize: 5 @ 0.
toolbar
addMorphBack: (self
createButtonLabel: 'r-unused'
action: #removeUntranslatedButUnusedStrings
help: 'Remove all the strings that are not used by the system').
^ toolbar!
----- Method: LanguageEditor>>createUpdatingButtonWording:action:help: (in category 'initialization - toolbar') -----
createUpdatingButtonWording: wordingSelector action: actionSelector help: helpString
"create a toolbar for the receiver"
| button |
button := (UpdatingSimpleButtonMorph newWithLabel: '-') target: self;
wordingSelector: wordingSelector;
actionSelector: actionSelector;
setBalloonText: helpString translated;
color: translator defaultBackgroundColor twiceDarker;
borderWidth: 1;
borderColor: #raised; cornerStyle: #square.
""
^ button!
----- Method: LanguageEditor>>delete (in category 'open/close') -----
delete
"Remove the receiver as a submorph of its owner"
self model: nil.
super delete !
----- Method: LanguageEditor>>deselectAllTranslation (in category 'gui methods') -----
deselectAllTranslation
selectedTranslations := IdentitySet new.
self changed: #allSelections!
----- Method: LanguageEditor>>filterTranslations (in category 'gui methods') -----
filterTranslations
| filter |
filter := UIManager default
request: 'filter with
(empty string means no-filtering)' translated
initialAnswer: self translationsFilter.
self filterTranslations: filter!
----- Method: LanguageEditor>>filterTranslations: (in category 'gui methods') -----
filterTranslations: aString
| filter |
filter := aString ifNil:[''].
""
translationsFilter := filter.
self refreshTranslations.
!
----- Method: LanguageEditor>>filterUntranslated (in category 'gui methods') -----
filterUntranslated
| filter |
filter := UIManager default
request: 'filter with
(empty string means no-filtering)' translated
initialAnswer: self untranslatedFilter.
self filterUntranslated: filter!
----- Method: LanguageEditor>>filterUntranslated: (in category 'gui methods') -----
filterUntranslated: aString
| filter |
filter := aString
ifNil: [''].
""
untranslatedFilter := filter.
self refreshUntranslated!
----- Method: LanguageEditor>>getText (in category 'gui methods') -----
getText
| menu |
menu := MenuMorph new defaultTarget: self.
""
menu
add: 'gettext template' translated
target: self
selector: #getTextExportTemplate.
menu lastItem setBalloonText: 'exports the translations to gettext separated format.' translated.
menu
add: 'gettext export' translated
target: self
selector: #getTextExport.
menu lastItem setBalloonText: 'Exports the translations to GetText format.' translated.
""
menu
add: 'gettext import' translated
target: self
selector: #getTextImport.
menu lastItem setBalloonText: 'Imports the translations from GetText format.' translated.
""
menu popUpInWorld!
----- Method: LanguageEditor>>getTextExport (in category 'gui methods') -----
getTextExport
Cursor wait
showWhile: [GetTextExporter new exportTranslator: self model]!
----- Method: LanguageEditor>>getTextExportTemplate (in category 'gui methods') -----
getTextExportTemplate
Cursor wait
showWhile: [GetTextExporter new exportTemplate] !
----- Method: LanguageEditor>>getTextImport (in category 'gui methods') -----
getTextImport
| menu |
menu := MenuMorph new defaultTarget: self.
menu addTitle: 'Choose translation file' translated.
menu add: 'All *.po files' translated action: #getTextImportAll.
menu add: 'Choose a file' translated action: #getTextImportAFile.
menu popUpInWorld!
----- Method: LanguageEditor>>getTextImportAFile (in category 'gui methods') -----
getTextImportAFile
| result |
result := (StandardFileMenu new pattern: '*.po';
oldFileFrom: (FileDirectory default directoryNamed: 'po')) startUpWithCaption: 'Select a File:' translated.
result
ifNil: [^ self].
self
withUnboundModelDo: [:trans | Cursor wait
showWhile: [GetTextImporter new
import: trans
fileNamed: (result directory fullNameFor: result name)]]!
----- Method: LanguageEditor>>getTextImportAll (in category 'gui methods') -----
getTextImportAll
self
withUnboundModelDo: [:trans | Cursor wait
showWhile: [GetTextImporter import: trans allDirectory: FileDirectory default]].
self refreshBoth!
----- Method: LanguageEditor>>identifyUnusedStrings (in category 'stef') -----
identifyUnusedStrings
"self new identifyUnusedStrings"
translationsList getList
do: [:each |
Transcript show: each.
Transcript show: (Smalltalk
allSelect: [:method | method
hasLiteralSuchThat: [:lit | lit isString
and: [lit includesSubstring: each caseSensitive: true]]]) size printString; cr]!
----- Method: LanguageEditor>>initializeNewerKeys (in category 'initialization') -----
initializeNewerKeys
newerKeys := Set new.
!
----- Method: LanguageEditor>>initializeOn: (in category 'initialization') -----
initializeOn: aLanguage
"initialize the receiver on aLanguage"
""
selectedTranslation := 0.
selectedUntranslated := 0.
selectedTranslations := IdentitySet new.
""
translator := aLanguage.
""
self model: aLanguage.
self setLabel: 'Language editor for: ' translated , self translator name.
""
self initializeToolbars.
self initializePanels.
self initializeStatusbar.
self initializeNewerKeys.
!
----- Method: LanguageEditor>>initializePanels (in category 'initialization') -----
initializePanels
"initialize the receiver's panels"
translationsList := PluggableListMorphOfMany
on: self
list: #translations
primarySelection: #selectedTranslation
changePrimarySelection: #selectedTranslation:
listSelection: #selectedTranslationsAt:
changeListSelection: #selectedTranslationsAt:put:
menu: #translationsMenu:
keystroke: #translationsKeystroke:.
translationsList setBalloonText: 'List of all the translated phrases.' translated.
""
untranslatedList := PluggableListMorph
on: self
list: #untranslated
selected: #selectedUntranslated
changeSelected: #selectedUntranslated:
menu: #untranslatedMenu:
keystroke: #untranslatedKeystroke:.
untranslatedList setBalloonText: 'List of all the untranslated phrases.' translated.
""
translationText := PluggableTextMorph
on: self
text: #translation
accept: #translation:
readSelection: nil
menu: nil.
translationText setBalloonText: 'Translation for the selected phrase in the upper list.' translated.
""
self
addMorph: translationsList
frame: (0 @ 0.18 corner: 0.5 @ 0.66).
self
addMorph: untranslatedList
frame: (0.5 @ 0.18 corner: 1 @ 0.93).
self
addMorph: translationText
frame: (0 @ 0.66 corner: 0.5 @ 0.93).
self hResizing: #shrinkWrap!
----- Method: LanguageEditor>>initializeStatusbar (in category 'initialization - statusbar') -----
initializeStatusbar
"initialize the receiver's statusbar"
self
addMorph: self createStatusbar
frame: (0 @ 0.93 corner: 1 @ 1)!
----- Method: LanguageEditor>>initializeToolbars (in category 'initialization - toolbar') -----
initializeToolbars
"initialize the receiver's toolbar"
self
addMorph: self createMainToolbar
frame: (0 @ 0 corner: 1 @ 0.09).
""
self
addMorph: self createTranslationsToolbar
frame: (0 @ 0.09 corner: 0.5 @ 0.18).
self
addMorph: self createUntranslatedToolbar
frame: (0.5 @ 0.09 corner: 1 @ 0.18)!
----- Method: LanguageEditor>>loadFromFile (in category 'gui methods') -----
loadFromFile
| fileName |
fileName := self selectTranslationFileName.
fileName isNil
ifTrue: [""
self beep.
^ self].
""
Cursor wait
showWhile: [
self translator loadFromFileNamed: fileName.
self refreshBoth]!
----- Method: LanguageEditor>>mergeFromFile (in category 'gui methods') -----
mergeFromFile
| fileName |
fileName := self selectTranslationFileName.
fileName isNil
ifTrue: [""
self beep.
^ self].
""
Cursor wait
showWhile: [
self translator loadFromFileNamed: fileName.
self refreshBoth]!
----- Method: LanguageEditor>>newTranslations (in category 'gui methods') -----
newTranslations
"private - try to apply the translations as much as possible all
over the image"
| result newID |
result := UIManager default request: 'New locale ID string?' translated initialAnswer: Locale current determineLocaleID isoString.
result isEmpty
ifTrue: ["Do nothing"
^ self].
newID := LocaleID isoString: result.
InternalTranslator
newLocaleID: (LocaleID isoString: result).
self class openOn: newID!
----- Method: LanguageEditor>>numberOfTimesStringIsUsed: (in category 'stef') -----
numberOfTimesStringIsUsed: aString
^ (self systemNavigation allSelect: [:method | method
hasLiteralSuchThat: [:lit | lit isString
and: [lit includesSubstring: aString caseSensitive: true]]]) size!
----- Method: LanguageEditor>>okToChange (in category 'updating') -----
okToChange
"Allows a controller to ask this of any model"
self selectedTranslation isZero
ifTrue: [^ true].
""
translationText hasUnacceptedEdits
ifFalse: [^ true].
^ (CustomMenu confirm: 'Discard the changes to currently selected translated phrase?' translated)
and: [""
translationText hasUnacceptedEdits: false.
true]!
----- Method: LanguageEditor>>perform:orSendTo: (in category 'message handling') -----
perform: selector orSendTo: otherTarget
"I wish to intercept and handle selector myself"
^ self perform: selector!
----- Method: LanguageEditor>>phrase:translation: (in category 'gui methods') -----
phrase: phraseString translation: translationString
"set the models's translation for phraseString"
self translator phrase: phraseString translation: translationString.
self refreshBoth.
newerKeys add: phraseString.
!
----- Method: LanguageEditor>>phraseToTranslate (in category 'gui methods') -----
phraseToTranslate
"answer a phrase to translate. use the selected untranslated phrase or ask for a new one"
^ self selectedUntranslated isZero
ifTrue: [UIManager default
multiLineRequest: 'new phrase to translate' translated
centerAt: Sensor cursorPoint
initialAnswer: ''
answerHeight: 200]
ifFalse: [self untranslated at: self selectedUntranslated]!
----- Method: LanguageEditor>>printHeaderReportOn: (in category 'reporting') -----
printHeaderReportOn: aStream
"append to aStream a header report of the receiver with swiki
format"
aStream nextPutAll: '!!!!';
nextPutAll: ('Language: {1}' translated format: {self translator localeID isoString});
cr.
aStream nextPutAll: '- ';
nextPutAll: ('{1} translated phrases' translated format: {self translator translations size});
cr.
aStream nextPutAll: '- ';
nextPutAll: ('{1} untranslated phrases' translated format: {self translator untranslated size});
cr.
aStream cr; cr!
----- Method: LanguageEditor>>printReportOn: (in category 'reporting') -----
printReportOn: aStream
"append to aStream a report of the receiver with swiki format"
self printHeaderReportOn: aStream.
self printUntranslatedReportOn: aStream.
self printTranslationsReportOn: aStream!
----- Method: LanguageEditor>>printTranslationsReportOn: (in category 'reporting') -----
printTranslationsReportOn: aStream
"append to aStream a report of the receiver's translations"
| originalPhrases |
aStream nextPutAll: '!!';
nextPutAll: 'translations' translated;
cr.
originalPhrases := self translator translations keys asSortedCollection.
originalPhrases
do: [:each |
aStream
nextPutAll: ('|{1}|{2}|' format: {self asHtml: each. self
asHtml: (self translator translate: each)});
cr].
aStream cr; cr!
----- Method: LanguageEditor>>printUntranslatedReportOn: (in category 'reporting') -----
printUntranslatedReportOn: aStream
"append to aStream a report of the receiver's translations"
aStream nextPutAll: '!!';
nextPutAll: 'not translated' translated;
cr.
self untranslated asSortedCollection
do: [:each |
aStream
nextPutAll: ('|{1}|' format: {self asHtml: each});
cr].
aStream cr; cr!
----- Method: LanguageEditor>>refreshBoth (in category 'updating') -----
refreshBoth
self refreshUntranslated
!
----- Method: LanguageEditor>>refreshTranslations (in category 'updating') -----
refreshTranslations
"refresh the translations panel"
self selectedTranslation: 0.
translations := nil.
self changed: #translations.
!
----- Method: LanguageEditor>>refreshUntranslated (in category 'updating') -----
refreshUntranslated
"refresh the untranslated panel"
self refreshTranslations.
self selectedUntranslated: 0.
untranslated := nil.
self changed: #untranslated.
!
----- Method: LanguageEditor>>removeTranslatedButUnusedStrings (in category 'stef') -----
removeTranslatedButUnusedStrings
(self confirm: 'Are you sure that you want to remove unused strings?' translated)
ifFalse: [^ self].
translationsList getList
do: [:each |
| timesUsed |
timesUsed := self numberOfTimesStringIsUsed: each.
Transcript show: each.
Transcript show: timesUsed printString;
cr.
timesUsed isZero
ifTrue: [self translator removeTranslationFor: each]]!
----- Method: LanguageEditor>>removeTranslation (in category 'gui methods') -----
removeTranslation
"remove the selected translation"
| translation |
self selectedTranslation isZero
ifTrue: [""
self beep.
self inform: 'select the translation to remove' translated.
^ self].
""
translation := self translations at: self selectedTranslation.
""
(self
confirm: ('Removing "{1}".
Are you sure you want to do this?' translated format: {translation}))
ifFalse: [^ self].
""
self translator removeTranslationFor: translation.
self refreshBoth!
----- Method: LanguageEditor>>removeUntranslated (in category 'gui methods') -----
removeUntranslated
"remove the selected untranslated phrase"
| untrans |
self selectedUntranslated isZero
ifTrue: [""
self beep.
self inform: 'select the untranslated phrase to remove' translated.
^ self].
""
untrans := self untranslated at: self selectedUntranslated.
""
(self
confirm: ('Removing "{1}".
Are you sure you want to do this?' translated format: {untrans}))
ifFalse: [^ self].
""
self translator removeUntranslated: untrans!
----- Method: LanguageEditor>>removeUntranslatedButUnusedStrings (in category 'stef') -----
removeUntranslatedButUnusedStrings
(self confirm: 'Are you sure that you want to remove unused strings?' translated)
ifFalse: [^ self].
untranslatedList getList
do: [:each |
| timesUsed |
timesUsed := self numberOfTimesStringIsUsed: each.
Transcript show: each.
Transcript show: timesUsed printString;
cr.
timesUsed isZero
ifTrue: [self translator removeUntranslated: each]].
self refreshUntranslated.
!
----- Method: LanguageEditor>>report (in category 'gui methods') -----
report
self reportString openInWorkspaceWithTitle: 'report' translated!
----- Method: LanguageEditor>>reportString (in category 'reporting') -----
reportString
"answer a string with a report of the receiver"
| stream |
stream := String new writeStream.
self printReportOn: stream.
^ stream contents!
----- Method: LanguageEditor>>resetNewerKeys (in category 'gui methods') -----
resetNewerKeys
self initializeNewerKeys.
!
----- Method: LanguageEditor>>saveToFile (in category 'gui methods') -----
saveToFile
"save the translator to a file"
| fileName |
fileName := UIManager default request: 'file name' translated initialAnswer: translator localeID isoString , '.translation'.
(fileName isNil
or: [fileName isEmpty])
ifTrue: [
self beep.
^ self].
Cursor wait
showWhile: [
self translator saveToFileNamed: fileName]!
----- Method: LanguageEditor>>searchTranslation (in category 'gui methods') -----
searchTranslation
| search |
search := UIManager default request: 'search for' translated initialAnswer: ''.
(search isNil
or: [search isEmpty])
ifTrue: [
self beep.
^ self].
self searchTranslation: search!
----- Method: LanguageEditor>>searchTranslation: (in category 'gui methods') -----
searchTranslation: aString
| results index |
results := self translations
select: [:each | ""
('*' , aString , '*' match: each)
or: ['*' , aString , '*' match: (self translator translate: each)]].
""
results isEmpty
ifTrue: [""
self inform: 'no matches for' translated , ' ''' , aString , ''''.
^ self].
""
results size = 1
ifTrue: [""
self selectTranslationPhrase: results first.
^ self].
""
index := (PopUpMenu
labelArray: (results
collect: [:each | ""
(each copy replaceAll: Character cr with: $\)
, ' -> '
, ((self translator translate: each) copy replaceAll: Character cr with: $\)]))
startUpWithCaption: 'select the translation...' translated.
""
index isZero
ifTrue: [""
self beep.
^ self].
""
self
selectTranslationPhrase: (results at: index)!
----- Method: LanguageEditor>>searchUntranslated (in category 'gui methods') -----
searchUntranslated
| search |
search := UIManager default request: 'search for' translated initialAnswer: ''.
(search isNil
or: [search isEmpty])
ifTrue: [
self beep.
^ self].
self searchUntranslated: search!
----- Method: LanguageEditor>>searchUntranslated: (in category 'gui methods') -----
searchUntranslated: aString
| untranslateds results index |
untranslateds := self untranslated.
results := untranslateds
select: [:each | '*' , aString , '*' match: each].
""
results isEmpty
ifTrue: [""
self inform: 'no matches for' translated , ' ''' , aString , ''''.
^ self].
""
results size = 1
ifTrue: [""
self selectUntranslatedPhrase: results first.
^ self].
""
index := (PopUpMenu
labelArray: (results
collect: [:each | each copy replaceAll: Character cr with: $\]))
startUpWithCaption: 'select the untranslated phrase...' translated.
""
index isZero
ifTrue: [""
self beep.
^ self].
""
self
selectUntranslatedPhrase: (results at: index)!
----- Method: LanguageEditor>>selectAllTranslation (in category 'gui methods') -----
selectAllTranslation
selectedTranslations := (1 to: self translations size) asIdentitySet.
self changed: #allSelections!
----- Method: LanguageEditor>>selectNewerKeys (in category 'gui methods') -----
selectNewerKeys
| index |
self deselectAllTranslation.
newerKeys do: [:k |
index := self translations indexOf: k ifAbsent: [0].
index > 0 ifTrue: [
self selectedTranslationsAt: index put: true
].
].
!
----- Method: LanguageEditor>>selectTranslationFileName (in category 'gui methods') -----
selectTranslationFileName
"answer a file with a translation"
| file |
file := (StandardFileMenu oldFileMenu: FileDirectory default withPattern: '*.translation')
startUpWithCaption: 'Select the file...' translated.
^ file isNil
ifFalse: [file directory fullNameFor: file name]!
----- Method: LanguageEditor>>selectTranslationPhrase: (in category 'gui methods') -----
selectTranslationPhrase: phraseString
self selectedTranslation: (self translations indexOf: phraseString)!
----- Method: LanguageEditor>>selectUntranslatedPhrase: (in category 'gui methods') -----
selectUntranslatedPhrase: phraseString
self
selectedUntranslated: (self untranslated indexOf: phraseString)!
----- Method: LanguageEditor>>selectedTranslation (in category 'accessing') -----
selectedTranslation
"answer the selectedTranslation"
^ selectedTranslation!
----- Method: LanguageEditor>>selectedTranslation: (in category 'accessing') -----
selectedTranslation: anInteger
"change the receiver's selectedTranslation"
selectedTranslation := anInteger.
""
self changed: #selectedTranslation.
self changed: #translation!
----- Method: LanguageEditor>>selectedTranslationsAt: (in category 'accessing') -----
selectedTranslationsAt: index
^ selectedTranslations includes: index!
----- Method: LanguageEditor>>selectedTranslationsAt:put: (in category 'accessing') -----
selectedTranslationsAt: index put: value
value = true
ifTrue: [selectedTranslations add: index]
ifFalse: [selectedTranslations
remove: index
ifAbsent: []]!
----- Method: LanguageEditor>>selectedUntranslated (in category 'accessing') -----
selectedUntranslated
"answer the selectedUntranslated"
^ selectedUntranslated!
----- Method: LanguageEditor>>selectedUntranslated: (in category 'accessing') -----
selectedUntranslated: anInteger
"change the selectedUntranslated"
selectedUntranslated := anInteger.
""
self changed: #selectedUntranslated!
----- Method: LanguageEditor>>status (in category 'gui methods') -----
status
"answer a status string"
| translationsSize untranslatedSize |
translationsSize := self translator translations size.
untranslatedSize := self translator untranslated size.
^ '| {1} phrases | {2} translated | {3} untranslated |' translated format: {translationsSize + untranslatedSize. translationsSize. untranslatedSize}!
----- Method: LanguageEditor>>translate (in category 'gui methods') -----
translate
"translate a phrase"
| phrase |
phrase := self phraseToTranslate.
""
(phrase isNil
or: [phrase = ''])
ifTrue: [""
self beep.
^ self].
""
self translatePhrase: phrase.
self refreshBoth!
----- Method: LanguageEditor>>translatePhrase: (in category 'gui methods') -----
translatePhrase: aString
"translate aString"
| translation |
translation := UIManager default
multiLineRequest: 'translation for: ' translated , '''' , aString , ''''
centerAt: Sensor cursorPoint
initialAnswer: aString
answerHeight: 200.
(translation isNil
or: [translation = ''])
ifTrue: [""
self beep.
^ self].
self phrase: aString translation: translation!
----- Method: LanguageEditor>>translation (in category 'accessing') -----
translation
"answer the translation for the selected phrase"
self selectedTranslation isZero
ifTrue: [^ '<select a phrase from the upper list>' translated].
""
^ self translator
translate: (self translations at: self selectedTranslation)!
----- Method: LanguageEditor>>translation: (in category 'accessing') -----
translation: aStringOrText
"change the translation for the selected phrase"
| phrase |
self selectedTranslation isZero
ifTrue: [^ self].
phrase := self translations at: self selectedTranslation.
translator
phrase: phrase
translation: aStringOrText asString.
newerKeys add: phrase.
^ true!
----- Method: LanguageEditor>>translations (in category 'accessing') -----
translations
"answet the translator's translations"
| allTranslations filterString |
translations ifNotNil: [^translations].
allTranslations := self translator translations keys.
""
filterString := self translationsFilter.
""
filterString isEmpty
ifFalse: [allTranslations := allTranslations
select: [:each | ""
('*' , filterString , '*' match: each)
or: ['*' , filterString , '*'
match: (self translator translate: each)]]].
""
^ translations := allTranslations asSortedCollection asArray!
----- Method: LanguageEditor>>translationsFilter (in category 'accessing') -----
translationsFilter
^translationsFilter ifNil:['']!
----- Method: LanguageEditor>>translationsFilterWording (in category 'gui methods') -----
translationsFilterWording
^ (self translationsFilter isEmpty
ifTrue: ['filter' translated]
ifFalse: ['filtering: {1}' translated format:{self translationsFilter}]) !
----- Method: LanguageEditor>>translationsKeystroke: (in category 'gui methods') -----
translationsKeystroke: aChar
"Respond to a Command key in the translations list."
aChar == $x
ifTrue: [^ self removeTranslation].
aChar == $E
ifTrue: [^ self browseMethodsWithTranslation]!
----- Method: LanguageEditor>>translationsMenu: (in category 'gui methods') -----
translationsMenu: aMenu
^ aMenu add: 'remove (x)' translated action: #removeTranslation;
add: 'where (E)' translated action: #browseMethodsWithTranslation;
add: 'select all' translated action: #selectAllTranslation;
add: 'deselect all' translated action: #deselectAllTranslation;
add: 'select changed keys' translated action: #selectNewerKeys;
add: 'export selection' translated action: #codeSelectedTranslation;
add: 'export selection in do-it form' translated action: #codeSelectedTranslationAsMimeString;
add: 'reset changed keys' translated action: #resetNewerKeys;
yourself!
----- Method: LanguageEditor>>translator (in category 'private') -----
translator
^translator!
----- Method: LanguageEditor>>untranslated (in category 'accessing') -----
untranslated
"answer the translator's untranslated phrases"
| all filterString |
untranslated ifNotNil: [^ untranslated].
all := self translator untranslated.
""
filterString := self untranslatedFilter.
""
filterString isEmpty
ifFalse: [all := all
select: [:each | ""
('*' , filterString , '*' match: each)
or: ['*' , filterString , '*'
match: (self translator translate: each)]]].
""
^ untranslated := all asSortedCollection asArray!
----- Method: LanguageEditor>>untranslatedFilter (in category 'accessing') -----
untranslatedFilter
^ untranslatedFilter
ifNil: ['']!
----- Method: LanguageEditor>>untranslatedFilterWording (in category 'gui methods') -----
untranslatedFilterWording
^ self untranslatedFilter isEmpty
ifTrue: ['filter' translated]
ifFalse: ['filtering: {1}' translated format: {self untranslatedFilter}]!
----- Method: LanguageEditor>>untranslatedKeystroke: (in category 'gui methods') -----
untranslatedKeystroke: aChar
"Respond to a Command key in the translations list."
aChar == $t
ifTrue: [^ self translate].
aChar == $E
ifTrue: [^ self browseMethodsWithUntranslated]!
----- Method: LanguageEditor>>untranslatedMenu: (in category 'gui methods') -----
untranslatedMenu: aMenu
^ aMenu add: 'remove' translated action: #removeUntranslated;
add: 'translate (t)' translated action: #translate;
add: 'where (E)' translated action: #browseMethodsWithUntranslated;
yourself!
----- Method: LanguageEditor>>update: (in category 'updating') -----
update: aSymbol
"Receive a change notice from an object of whom the receiver
is a dependent."
super update: aSymbol.
""
aSymbol == #untranslated
ifTrue: [self refreshUntranslated].
aSymbol == #translations
ifTrue: [self refreshTranslations]!
----- Method: LanguageEditor>>withUnboundModelDo: (in category 'private') -----
withUnboundModelDo: aBlock
"Private - Evaluate aBlock with the receiver temporary
unbound from the model.
Useful to perform a batch of modifications to the model
without updating the view."
| formerModel |
formerModel := self model.
self model: nil.
[aBlock value: formerModel]
ensure: [self model: formerModel]!
More information about the Squeak-dev
mailing list
|