2816: Implement context for translations (largely taken from Teeworlds) r=Learath2 a=def-

Missing: scripts/languages doesn't work yet, but the context can be
added manually, see german.txt for an example.

Co-authored-by: def <dennis@felsin9.de>
This commit is contained in:
bors[bot] 2020-09-15 17:02:00 +00:00 committed by GitHub
commit 3b0bb7d777
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 454 additions and 181 deletions

View file

@ -307,6 +307,7 @@ Ping
Pistol
== Пісталет
[Demo browser]
Play
== Прагляд
@ -1158,6 +1159,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -310,6 +310,7 @@ Ping
Pistol
== Pištolj
[Demo browser]
Play
== Pogledaj
@ -1206,6 +1207,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
Manual %3d:%02d
==

View file

@ -325,6 +325,7 @@ Ping
Pistol
== Pistola
[Demo browser]
Play
== Assistir
@ -1236,3 +1237,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -307,6 +307,7 @@ Ping
Pistol
== Пистолет
[Demo browser]
Play
== Възпроизведи
@ -1158,6 +1159,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -305,6 +305,7 @@ Ping
Pistol
== Pistola
[Demo browser]
Play
== Reproduir
@ -1216,3 +1217,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -307,6 +307,7 @@ Ping
Pistol
== Пистолет
[Demo browser]
Play
== Пăхма
@ -1158,6 +1159,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -310,6 +310,7 @@ Ping
Pistol
== Pistolka
[Demo browser]
Play
== Přehrát
@ -1161,6 +1162,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -307,6 +307,7 @@ Ping
Pistol
== Pistol
[Demo browser]
Play
== Spil
@ -1158,6 +1159,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -319,6 +319,7 @@ Ping
Pistol
== Pistool
[Demo browser]
Play
== Spelen
@ -1229,6 +1230,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
Net
==

View file

@ -308,6 +308,7 @@ Ping
Pistol
== Pistooli
[Demo browser]
Play
== Toista
@ -1159,6 +1160,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -319,6 +319,7 @@ Ping
Pistol
== Pistolet
[Demo browser]
Play
== Jouer
@ -1247,3 +1248,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -324,6 +324,7 @@ Ping
Pistol
== Pistole
[Demo browser]
Play
== Abspielen
@ -1225,16 +1226,20 @@ Menu
== Menü
Warning
==
== Warnung
Speed
==
== Geschwindigkeit
Website
== Website
Server executable not found, can't run server
== Server-Programm nicht gefunden, kann Server nicht starten
[Start menu]
Play
== Spielen
https://wiki.ddnet.tw/
==
Website
==
Server executable not found, can't run server
==

View file

@ -310,6 +310,7 @@ Ping
Pistol
== Πιστόλι
[Demo browser]
Play
== Παίξτε
@ -1158,6 +1159,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -304,6 +304,7 @@ Ping
Pistol
== Pisztoly
[Demo browser]
Play
== Játék
@ -1228,3 +1229,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -311,6 +311,7 @@ Ping
Pistol
== Pistola
[Demo browser]
Play
== Riproduci
@ -1164,6 +1165,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -307,6 +307,7 @@ Ping
Pistol
== ピストル
[Demo browser]
Play
== プレイ
@ -1158,6 +1159,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -303,6 +303,7 @@ Ping
Pistol
== 권총
[Demo browser]
Play
== 플레이
@ -1157,6 +1158,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -366,6 +366,7 @@ Ping
Pistol
== Тапанча
[Demo browser]
Play
== Көрүү
@ -1149,6 +1150,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -308,6 +308,7 @@ Ping
Pistol
== Pistol
[Demo browser]
Play
== Spill
@ -1224,3 +1225,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -204,157 +204,9 @@ Ping
== ﮓﻨﯿﭘ
Pistol
== ﺮﯿﺗ ﺖﻔﻫ
[Demo browser]
Play
== ﻥﺩﺮﻛ ىﺯﺎﺑ
Play background music
== ﻪﻨﯿﻣﺯ ﺲﭘ ﻚﯾﺯﻮﻣ ﻥﺩﺮﻛ ﺶﺨﭘ
Player
== ﻦﻜﯾﺯﺎﺑ
Player country:
== ﻦﻜﯾﺯﺎﺑ ﺭﻮﺸﻛ:
Player options
== ﻦﻜﯾﺯﺎﺑ ﺕﺎﻤﯿﻈﻨﺗ:
Players
== ﻥﺎﻨﻜﯾﺯﺎﺑ
Please balance teams!
== !ﺪﯿﻨﻛ ﻝﺩﺎﻌﺘﻣ ﺍﺭ ﻢﯿﺗ ﺎﻔﻄﻟ
Prev. weapon
== ﯽﻠﺒﻗ ﻪﺤﻠﺳﺍ
Quit
== ﻥﺪﺷ ﺝﺭﺎﺧ
Reason:
== ﻞﯿﻟﺩ:
Red team
== ﺰﻣﺮﻗ ﻢﯿﺗ
Red team wins!
== !ﺪﺷ ﻩﺪﻧﺮﺑ ﺰﻣﺮﻗ ﻢﯿﺗ
Refresh
== ﻩﺭﺎﺑﻭﺩ ىﺭﺍﺬﮔﺭﺎﺑ
Refreshing master servers
== ﯽﻠﺻﺍ ىﺎﻫ ﺭﻭﺮﺳ ﻩﺭﺎﺑﻭﺩ ىﺭﺍﺬﮔﺭﺎﺑ
Remote console
== ﻝﻮﺴﻨﮐ ﻝﺮﺘﻨﮐ
Remove
== ﻥﺩﺮﮐ ﻑﺬﺣ
Remove friend
== ﺖﺳﻭﺩ ﻥﺩﺮﮐ ﻑﺪﺣ
Rename
== ﻡﺎﻧ ﺮﯿﯿﻐﺗ
Rename demo
== ﻮﻣﺩ ﻡﺎﻧ ﺮﯿﯿﻐﺗ
Reset filter
== ﺮﺘﻠﯿﻓ ﻩﺭﺎﺑﻭﺩ ﻢﯿﻈﻨﺗ
Sample rate
== ﻪﻧﻮﻤﻧ ﺶﺠﻨﺳ
Score
== ﺯﺎﯿﺘﻣﺍ
Score limit
== ﺯﺎﯿﺘﻣﺍ ﺪﺣ
Scoreboard
== ﯼﺪﻨﺑ ﻪﺒﺗﺭ
Screenshot
== ﻪﺤﻔﺻ ﺯﺍ ﯼﺭﺍﺩﺮﺑ ﺲﮑﻋ
Server address:
== :ﺭﻭﺮﺳ ﺱﺭﺩﺁ
Server details
== ﺭﻭﺮﺳ ﺕﺎﯿﺋﺰﺟ
Server filter
== ﺭﻭﺮﺳ ﯽﮔﮋﯾﻭ
Server info
== ﺭﻭﺮﺳ ﺕﺎﻋﻼﻃﺍ
Server not full
== ﻩﺪﺸﻧ ﺮﭘ ﺭﻭﺮﺳ
Shotgun
== ىﺍ ﻪﻤﭼﺎﺳ ﮓﻨﻔﺗ
Show chat
== ﺖﭼ ﻥﺩﺍﺩ ﻥﺎﺸﻧ
Show friends only
== ﻥﺎﺘﺳﻭﺩ ﺶﯾﺎﻤﻧ ﻂﻘﻓ
Show ingame HUD
== ﯼﺯﺎﺑ ﺭﺩ HUD ﻥﺩﺍﺩ ﻥﺎﺸﻧ
Show name plates
== ﻢﺳﺍ ﻥﺩﺍﺩ ﻥﺎﺸﻧ
Show only chat messages from friends
== ﻥﺎﺘﺳﻭﺩ ﯼﺎﻫ ﻡﺎﯿﭘ ﻥﺩﺍﺩ ﻥﺎﺸﻧ ﻂﻘﻓ
Show only supported
== ﺪﻧﻮﺷ ﯽﻣ ﯽﻧﺎﺒﯿﺘﺸﭘ ﻪﻛ ﯽﯾﺎﻫ ﺖﻟﺎﺣ ﺶﯾﺎﻤﻧ ﻂﻘﻓ
Skins
== ﻦﯿﮑﺳﺍ
Sound
== ﺍﺪﺻ
Sound error
== ﺍﺪﺻ ﯼﺎﻄﺧ
Spectate
== ﺎﺷﺎﻤﺗ
Spectate next
== ﯼﺪﻌﺑ ﯼ ﺎﺷﺎﻤﺗ
Spectate previous
== ﯽﻠﺒﻗ ﯼ ﺎﺷﺎﻤﺗ
Spectator mode
== ﺮﮔﺎﺷﺎﻤﺗ ﺖﻟﺎﺣ
Spectators
== ﺮﮔﺎﺷﺎﻤﺗ
Standard gametype
== ﯼﺯﺎﺑ ﺩﺭﺍﺪﻧﺎﺘﺳﺍ ﯼﺎﻫ ﻝﺪﻣ
Standard map
== ﺩﺭﺍﺪﻧﺎﺘﺳﺍ ﯼﺎﻫ ﭗﻣ
Stop record
== ﻥﺩﺮﮐ ﻂﺒﺿ ﻒﻗﻮﺗ
Strict gametype filter
== ﯼﺯﺎﺑ ﺩﻮﻣ ﺮﺘﻠﯿﻓ
Sudden Death
== ﯽﻧﺎﻬﮔﺎﻧ ﮒﺮﻣ
Switch weapon on pickup
== ﻥﺪﺷ ﻪﺘﺷﺍﺩﺭﻭ ﺕﺭﻮﺻ ﺭﺩ ﻪﺤﻠﺳﺍ ﺮﯿﯿﻐﺗ
Team
== ﻢﯿﺗ
Team chat
== ﻢﯿﺗ ﺖﭼ
The audio device couldn't be initialised.
== .ﺪﺸﻧ ﻥﺪﺷ ﺐﺼﻧ ﻪﺑ ﻖﻓﻮﻣ ﺍﺪﺻ ﻩﺎﮕﺘﺳﺩ
The server is running a non-standard tuning on a pure game type.
== .ﺖﺳﺍ ﺮﮕﯾﺩ ﯼﺯﺎﺑ ﻝﺪﻣ ﮏﯾ ﯼﻭﺭ ﻭ ﺩﺭﺍﺪﻧﺎﺘﺳﺍ ﺮﯿﻏ ﺕﺎﻤﯿﻈﻨﺗ ﯼﺍﺭﺍﺩ ﺍﺮﺟﺍ ﻝﺎﺣ ﺭﺩ ﺭﻭﺮﺳ
There's an unsaved map in the editor, you might want to save it before you quit the game.
== .ﯼﺯﺎﺑ ﺯﺍ ﺝﻭﺮﺧ ﺯﺍ ﻼﺒﻗ ﺪﯿﻨﮐ ﻩﺮﯿﺧﺫ ﺍﺭ ﻥﺁ ﺪﯿﻫﺍﻮﺨﺑ ﺎﻤﺷ ﺖﺳﺍ ﻦﮑﻤﻣ , ﺮﮕﻨﯾﻭﺪﺗ ﺭﺩ ﻩﺪﺸﻧ ﻩﺮﯿﺧﺫ ﭗﻣ ﻦﯾﺍ
Time limit
== ﻥﺎﻣﺯ ﺖﯾﺎﻬﻧ
Time limit: %d min
== ﻪﻘﯿﻗﺩ d% :ﻥﺎﻣﺯ ﺖﯾﺎﻬﻧ
Try again
== ﻩﺭﺎﺑﻭﺩ ﺵﻼﺗ
Type
== ﻝﺪﻣ
Unable to delete the demo
== ﺩﺮﮐ ﮎﺎﭘ ﺍﺭ ﻮﻣﺩ ﻦﯾﺍ ﻥﺍﻮﺘﯿﻤﻧ
Unable to rename the demo
== ﺩﺮﮐ ﺽﻮﻋ ﺍﺭ ﻮﻣﺩ ﻦﯾﺍ ﻢﺳﺍ ﻥﺍﻮﺘﯿﻤﻧ
Use sounds
== ﺍﺪﺻ ﺯﺍ ﻩﺩﺎﻔﺘﺳﺍ
Use team colors for name plates
== ﻢﺳﺍ ﯼﺍﺮﺑ ﻢﯿﺗ ﮓﻧﺭ ﺯﺍ ﻩﺩﺎﻔﺘﺳﺍ
V-Sync
== V-Sync
Version
== ﻪﺨﺴﻧ
Vote command:
== ﯽﺠﻨﺳ ﺮﻈﻧ ﺕﺍﺭﻮﺘﺳﺩ:
Vote description:
== :ﯽﺠﻨﺳ ﺮﻈﻧ ﺕﺎﺤﯿﺿﻮﺗ
Vote no
== ﻪﻧ ﯼﺍﺭ
Vote yes
== ﻪﻠﺑ ﯼﺍﺭ
Voting
== ﯼﺮﯿﮔ ﯼﺍﺭ
Warmup
== ﺪﯿﻨﮐ ﻪﻠﺠﻋ
Weapon
== ﻪﺤﻠﺳﺍ
Yes
== ﻪﻠﺑ
You must restart the game for all settings to take effect.
== ﺪﻧﻮﺷ ﻡﺎﺠﻧﺍ ﺕﺎﻤﯿﻈﻨﺗ ﻪﮑﻨﯾﺍ ﯼﺍﺮﺑ ﺪﯿﻨﮐ ﯼﺭﺍﺰﮔﺭﺎﺑ ﻩﺭﺎﺑﻭﺩ ﺍﺭ ﯼﺯﺎﺑ ﺪﯾﺎﺑ ﺎﻤﺷ
##### ﻪﻤﺟﺮﺗ ﻪﺑ ﺝﺎﯿﺘﺣﺍ #####
Borderless window
== ﺯﺮﻣ ﻩﺮﺠﻨﭘ
Demo
@ -786,24 +638,231 @@ The width or height of texture %s is not divisible by 16, which might cause visu
Warning
==
Team
==
Sudden Death
==
Warmup
==
Please balance teams!
==
Reason:
==
Vote yes
==
Vote no
==
Spectate
==
Menu
==
Players
==
Server info
==
The server is running a non-standard tuning on a pure game type.
==
Rename demo
==
Remove friend
==
Sound error
==
The audio device couldn't be initialised.
==
Try again
==
Quit
==
Use k key to kill (restart), q to pause and watch other players. See settings for other key binds.
==
There's an unsaved map in the editor, you might want to save it before you quit the game.
==
Yes
==
Country / Region
==
Unable to delete the demo
==
Unable to rename the demo
==
Show chat
==
Use sounds
==
Speed
==
Show ingame HUD
==
Type
==
Refreshing master servers
==
Server filter
==
Server not full
==
Show friends only
==
Standard gametype
==
Standard map
==
Strict gametype filter
==
Server address:
==
Player country:
==
Reset filter
==
Server details
==
Scoreboard
==
Remove
==
Refresh
==
Rename
==
Stop record
==
Player options
==
Player
==
Version
==
Score limit
==
Time limit
==
Vote description:
==
Vote command:
==
Switch weapon on pickup
==
Show only chat messages from friends
==
Show name plates
==
Use team colors for name plates
==
Skip the main menu
==
Skins
==
Shotgun
==
Prev. weapon
==
Team chat
==
Spectator mode
==
Spectate next
==
Spectate previous
==
Remote console
==
Screenshot
==
Weapon
==
Voting
==
Show only supported
==
V-Sync
==
may cause delay
==
Play background music
==
Sample rate
==
Sound
==
You must restart the game for all settings to take effect.
==
Client message
==
@ -830,3 +889,22 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
Time limit: %d min
==
Spectators
==
Score
==
Red team wins!
==
Red team
==

View file

@ -312,6 +312,7 @@ Ping
Pistol
== Pistolet
[Demo browser]
Play
== Graj
@ -1228,3 +1229,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -322,6 +322,7 @@ Ping
Pistol
== Pistola
[Demo browser]
Play
== Ver
@ -1174,6 +1175,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -316,6 +316,7 @@ Ping
Pistol
== Pistol
[Demo browser]
Play
== Redă
@ -1164,6 +1165,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -314,6 +314,7 @@ Ping
Pistol
== Пистолет
[Demo browser]
Play
== Просмотр

View file

@ -310,6 +310,7 @@ Ping
Pistol
== Pištolj
[Demo browser]
Play
== Pokreni
@ -1159,6 +1160,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -341,6 +341,7 @@ Ping
Pistol
== 手枪
[Demo browser]
Play
== 播放
@ -1234,3 +1235,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -307,6 +307,7 @@ Ping
Pistol
== Pištoľ
[Demo browser]
Play
== Prehrať
@ -1158,6 +1159,10 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==
DDNet %s is out!
==

View file

@ -316,6 +316,7 @@ Ping
Pistol
== Pistola
[Demo browser]
Play
== Reproducir
@ -1229,3 +1230,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -309,6 +309,7 @@ Ping
Pistol
== Pistol
[Demo browser]
Play
== Spela
@ -1225,3 +1226,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -335,6 +335,7 @@ Ping
Pistol
== 手槍
[Demo browser]
Play
== 播放
@ -1228,3 +1229,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -312,6 +312,7 @@ Ping
Pistol
== Tabanca
[Demo browser]
Play
== Oynat
@ -1228,3 +1229,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -238,6 +238,7 @@ Ping
Pistol
== Пістолет
[Demo browser]
Play
== Перегляд
@ -1223,3 +1224,7 @@ Server executable not found, can't run server
Editor
==
[Start menu]
Play
==

View file

@ -48,7 +48,9 @@ if append_missing:
if content[-1] != "\n":
content.append("\n")
for i, miss in enumerate(missing):
content.append(local[miss]+"\n== \n\n")
if local[miss][1] != "":
content.append("["+local[miss][1]+"]\n")
content.append(local[miss][0]+"\n== \n\n")
content[-1] = content[-1][:-1]
open(outfile, "w").write("".join(content))

View file

@ -10,15 +10,23 @@ class LanguageDecodeError(Exception):
def decode(fileobj, elements_per_key):
data = {}
current_context = ""
current_key = None
for index, line in enumerate(fileobj):
line = line.encode("utf-8").decode("utf-8-sig")
line = line[:-1]
context = ""
if line and line[-1] == "\r":
line = line[:-1]
if not line or line[:1] == "#":
current_context = ""
continue
if line[:3] == "== ":
if line[0] == "[":
if line[-1] != "]":
raise LanguageDecodeError("Invalid context string", fileobj.name, index)
current_context = line[1:-1]
elif line[:3] == "== ":
if len(data[current_key]) >= 1+elements_per_key:
raise LanguageDecodeError("Wrong number of elements per key", fileobj.name, index)
if current_key:
@ -32,8 +40,8 @@ def decode(fileobj, elements_per_key):
data[current_key].append(index)
if line in data:
raise LanguageDecodeError("Key defined multiple times: " + line, fileobj.name, index)
data[line] = [index]
current_key = line
data[(line, current_context)] = [index]
current_key = (line, current_context)
if len(data[current_key]) != 1+elements_per_key:
raise LanguageDecodeError("Wrong number of elements per key", fileobj.name, index)
data[current_key].append(index+1)
@ -42,7 +50,7 @@ def decode(fileobj, elements_per_key):
def check_file(path):
with open(path) as fileobj:
matches = re.findall("Localize\s*\(\s*\"([^\"]+)\"\s*\)", fileobj.read())
matches = re.findall("Localize\s*\(\s*\"([^\"]+)\"(?:\s*,\s*\"([^\"]+)\")?\s*\)", fileobj.read())
return matches

View file

@ -1245,7 +1245,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
}
static int s_PlayButton = 0;
if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir?Localize("Open"):Localize("Play"), 0, &PlayRect) || Activated || Input()->KeyPress(KEY_P))
if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir ? Localize("Open") : Localize("Play", "Demo browser"), 0, &PlayRect) || Activated || Input()->KeyPress(KEY_P))
{
if(m_DemolistSelectedIndex >= 0)
{

View file

@ -155,7 +155,7 @@ void CMenus::RenderStartMenu(CUIRect MainView)
Menu.HSplitBottom(5.0f, &Menu, 0); // little space
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_PlayButton;
if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)) || m_EnterPressed || CheckHotKey(KEY_P))
if(DoButton_Menu(&s_PlayButton, Localize("Play", "Start menu"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)) || m_EnterPressed || CheckHotKey(KEY_P))
{
NewPage = g_Config.m_UiPage >= PAGE_INTERNET && g_Config.m_UiPage <= PAGE_KOG ? g_Config.m_UiPage : PAGE_DDNET;
}

View file

@ -8,13 +8,13 @@
#include <engine/console.h>
#include <engine/storage.h>
const char *Localize(const char *pStr)
const char *Localize(const char *pStr, const char *pContext)
{
const char *pNewStr = g_Localization.FindString(str_quickhash(pStr));
const char *pNewStr = g_Localization.FindString(str_quickhash(pStr), str_quickhash(pContext));
return pNewStr ? pNewStr : pStr;
}
CLocConstString::CLocConstString(const char *pStr)
CLocConstString::CLocConstString(const char *pStr, const char *pContext)
{
m_pDefaultStr = pStr;
m_Hash = str_quickhash(m_pDefaultStr);
@ -24,7 +24,7 @@ CLocConstString::CLocConstString(const char *pStr)
void CLocConstString::Reload()
{
m_Version = g_Localization.Version();
const char *pNewStr = g_Localization.FindString(m_Hash);
const char *pNewStr = g_Localization.FindString(m_Hash, m_ContextHash);
m_pCurrentStr = pNewStr;
if(!m_pCurrentStr)
m_pCurrentStr = m_pDefaultStr;
@ -36,10 +36,11 @@ CLocalizationDatabase::CLocalizationDatabase()
m_CurrentVersion = 0;
}
void CLocalizationDatabase::AddString(const char *pOrgStr, const char *pNewStr)
void CLocalizationDatabase::AddString(const char *pOrgStr, const char *pNewStr, const char *pContext)
{
CString s;
s.m_Hash = str_quickhash(pOrgStr);
s.m_ContextHash = str_quickhash(pContext);
s.m_Replacement = *pNewStr ? pNewStr : pOrgStr;
m_Strings.add(s);
}
@ -63,6 +64,7 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon
pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", aBuf);
m_Strings.clear();
char aContext[512];
char aOrigin[512];
CLineReader LineReader;
LineReader.Init(IoHandle);
@ -77,6 +79,23 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon
if(pLine[0] == '#') // skip comments
continue;
if(pLine[0] == '[') // context
{
size_t Len = str_length(pLine);
if(Len < 1 || pLine[Len - 1] != ']')
{
str_format(aBuf, sizeof(aBuf), "malform context line (%d): %s", Line, pLine);
pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", aBuf);
continue;
}
str_copy(aContext, pLine + 1, Len - 1);
pLine = LineReader.Get();
}
else
{
aContext[0] = '\0';
}
str_copy(aOrigin, pLine, sizeof(aOrigin));
char *pReplacement = LineReader.Get();
Line++;
@ -94,7 +113,7 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon
}
pReplacement += 3;
AddString(aOrigin, pReplacement);
AddString(aOrigin, pReplacement, aContext);
}
io_close(IoHandle);
@ -102,14 +121,27 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon
return true;
}
const char *CLocalizationDatabase::FindString(unsigned Hash)
const char *CLocalizationDatabase::FindString(unsigned Hash, unsigned ContextHash)
{
CString String;
String.m_Hash = Hash;
String.m_ContextHash = ContextHash;
sorted_array<CString>::range r = ::find_binary(m_Strings.all(), String);
if(r.empty())
return 0;
return r.front().m_Replacement;
unsigned DefaultHash = str_quickhash("");
unsigned DefaultIndex = 0;
for(unsigned i = 0; i < r.size() && r.index(i).m_Hash == Hash; ++i)
{
const CString &rStr = r.index(i);
if(rStr.m_ContextHash == ContextHash)
return rStr.m_Replacement;
else if(rStr.m_ContextHash == DefaultHash)
DefaultIndex = i;
}
return r.index(DefaultIndex).m_Replacement;
}
CLocalizationDatabase g_Localization;

View file

@ -11,13 +11,14 @@ class CLocalizationDatabase
{
public:
unsigned m_Hash;
unsigned m_ContextHash;
// TODO: do this as an const char * and put everything on a incremental heap
string m_Replacement;
bool operator <(const CString &Other) const { return m_Hash < Other.m_Hash; }
bool operator <=(const CString &Other) const { return m_Hash <= Other.m_Hash; }
bool operator ==(const CString &Other) const { return m_Hash == Other.m_Hash; }
bool operator<(const CString &Other) const { return m_Hash < Other.m_Hash || (m_Hash == Other.m_Hash && m_ContextHash < Other.m_ContextHash); }
bool operator<=(const CString &Other) const { return m_Hash < Other.m_Hash || (m_Hash == Other.m_Hash && m_ContextHash <= Other.m_ContextHash); }
bool operator==(const CString &Other) const { return m_Hash == Other.m_Hash && m_ContextHash == Other.m_ContextHash; }
};
sorted_array<CString> m_Strings;
@ -31,8 +32,8 @@ public:
int Version() { return m_CurrentVersion; }
void AddString(const char *pOrgStr, const char *pNewStr);
const char *FindString(unsigned Hash);
void AddString(const char *pOrgStr, const char *pNewStr, const char *pContext);
const char *FindString(unsigned Hash, unsigned ContextHash);
};
extern CLocalizationDatabase g_Localization;
@ -42,9 +43,11 @@ class CLocConstString
const char *m_pDefaultStr;
const char *m_pCurrentStr;
unsigned m_Hash;
unsigned m_ContextHash;
int m_Version;
public:
CLocConstString(const char *pStr);
CLocConstString(const char *pStr, const char *pContext = "");
void Reload();
inline operator const char *()
@ -55,7 +58,6 @@ public:
}
};
extern const char *Localize(const char *pStr)
GNUC_ATTRIBUTE((format_arg(1)));
extern const char *Localize(const char *pStr, const char *pContext = "")
GNUC_ATTRIBUTE((format_arg(1)));
#endif