*discontinued* Advanced TranslationStrings
Posted: Fri Jan 15, 2016 6:06 pm
DISCONTINUED
Features implemented by this package are now possible without it due to implementing .tokenized method directly into Source.Python: https://github.com/Source-Python-Dev-Team/Source.Python/commit/520cc3b8d282651cba9304020eb828776bb4b0ac
Note that this package used .tokenize method.
Source.Python Advanced TranslationStrings (custom package)
Download: https://github.com/KirillMysnik/sp-advanced-ts-package/releases/latest
The package includes 2 classes:
Now, why we would need all this. Here's an example plugin that utilizes the package:
cstrike/resource/source-python/translations/advanced_ts_test.ini
cstrike/addons/source-python/plugins/advanced_ts_test/advanced_ts_test.py
Import/constants
Now let's create a simple popup but we will take advantage of .tokenize. The thing is that we want to show 'your_team_is' translation but one of its tokens, 'team', is a translation itself. What is more, we should add an ability to add a translated "(DISABLED)" phrase to options we want to disable. Here it is (for tokens explanation look at the advanced_ts.ini above):
Then let's think about more complex structures. For example, chat message. It may include a tag - in this case tag will need colors, as you can see in strings file. So we will need to tokenize it with color_tokens (see import/constants section). Then there's a message itself. Not only should it accept various tokens which in turn may turn out to be even more TranslationStrings instanes, but it also should receive color_tokens.
Let's see create tell() function which takes care of all of that. I will actually firstly show you Python 3.5 version which won't work with current SP builds, but it's easier to read.
Finally, let's use all of that
Result:

The package can be found here
Sample plugin is all given above, the one thing is that here's working Python 3.4 version of tell():
I hope some ideas of this package can make their way into Source.Python. Thanks.
Features implemented by this package are now possible without it due to implementing .tokenized method directly into Source.Python: https://github.com/Source-Python-Dev-Team/Source.Python/commit/520cc3b8d282651cba9304020eb828776bb4b0ac
Note that this package used .tokenize method.
Source.Python Advanced TranslationStrings (custom package)
Download: https://github.com/KirillMysnik/sp-advanced-ts-package/releases/latest
The package includes 2 classes:
- BaseLangStrings - basically LangStrings class but after initialization replaces all TranslationStrings instances with the given base:
Syntax: Select all
class BaseLangStrings(LangStrings):
"""
This is a LangStrings class but after initialization replaces
all TranslationStrings values with instances of the given
dict-inherited base class.
"""
def __init__(self, infile, encoding='utf_8', base=RecursiveTS):
super().__init__(infile, encoding)
for key, value in self.items():
if isinstance(value, TranslationStrings):
new_translation_strings = base()
for key_, value_ in value.items():
new_translation_strings[key_] = value_
self[key] = new_translation_strings
If base kwarg is implemented in SP's LangStrings, there's no need to keep this class in the package. - RecursiveTS - provides new .tokenize method and makes .get_string method recursive
Syntax: Select all
class RecursiveTS(TranslationStrings):
"""
This class provides recursive get_string method.
"""
def get_string(self, language=None, **tokens):
"""
Exposes packed tokens (self.tokens) and additional tokens (**tokens).
"""
# Deeply expose all TranslationStrings instances in self.tokens
for token_name, token in self.tokens.items():
if isinstance(token, TranslationStrings):
new_tokens = self.tokens.copy()
del new_tokens[token_name]
# Pass additional tokens - these will NOT be used to
# continue deep exposition but will be used to call
# super().get_string.
token = token.get_string(language, **tokens)
self.tokens[token_name] = token
# Then shallowly expose all TranslationsStrings instances in **tokens
for token_name, token in tokens.items():
if isinstance(token, TranslationStrings):
# Don't pass any additional tokens.
# The token should either be trivial (regular
# TranslationStrings instance) or rely on itself (self.tokens).
tokens[token_name] = token.get_string(language)
# Finally with all of the tokens exposed, call the original get_string
return super().get_string(language, **tokens)
def tokenize(self, **tokens):
"""Return new TranslationStrings object with updated tokens."""
rs = type(self)()
for key, value in self.items():
rs[key] = value
rs.tokens = self.tokens.copy()
rs.tokens.update(tokens)
return rs
Now, why we would need all this. Here's an example plugin that utilizes the package:
cstrike/resource/source-python/translations/advanced_ts_test.ini
Code: Select all
[popup title]
en="My Popup"
[popup base]
en="{text}"
[popup base disabled]
en="(DISABLED) {text}"
[popup slay_team]
en="Slay {team} players"
[team_alpha]
en="Alpha"
[team_bravo]
en="Bravo"
[team_charlie]
en="Charlie"
[chat base]
en="{colorful_sign}{text}"
[chat base with_tag]
en="{colorful_sign}{tag} {text}"
[tag]
en="{color_special}[{color_default}My Plugin{color_special}]{color_default}"
[your_team_is]
en="Your team is team {team}"
cstrike/addons/source-python/plugins/advanced_ts_test/advanced_ts_test.py
Import/constants
Syntax: Select all
from colors import Color
from events import Event
from menus import PagedMenu
from menus import PagedOption
from messages import SayText2
from players.entity import Player
from players.helpers import index_from_userid
from advanced_ts import BaseLangStrings, RecursiveTS
COLORFUL_SIGN = '\x01'
COLOR_DEFAULT = Color(255, 255, 255)
COLOR_SPECIAL = Color(255, 0, 0)
strings = BaseLangStrings('advanced_ts_test', base=RecursiveTS)
color_tokens = {
'color_default': COLOR_DEFAULT,
'color_special': COLOR_SPECIAL,
}
Now let's create a simple popup but we will take advantage of .tokenize. The thing is that we want to show 'your_team_is' translation but one of its tokens, 'team', is a translation itself. What is more, we should add an ability to add a translated "(DISABLED)" phrase to options we want to disable. Here it is (for tokens explanation look at the advanced_ts.ini above):
Syntax: Select all
popup = PagedMenu(title=strings['popup title'])
# Regular option
popup.append(PagedOption(
text=strings['popup base'].tokenize(
text=strings['popup slay_team'].tokenize(
team=strings['team_alpha']
)
)
))
# "(DISABLED)" option
popup.append(PagedOption(
text=strings['popup base disabled'].tokenize(
text=strings['popup slay_team'].tokenize(
team=strings['team_bravo'],
)
),
highlight=False,
selectable=False
))
Then let's think about more complex structures. For example, chat message. It may include a tag - in this case tag will need colors, as you can see in strings file. So we will need to tokenize it with color_tokens (see import/constants section). Then there's a message itself. Not only should it accept various tokens which in turn may turn out to be even more TranslationStrings instanes, but it also should receive color_tokens.
Let's see create tell() function which takes care of all of that. I will actually firstly show you Python 3.5 version which won't work with current SP builds, but it's easier to read.
Syntax: Select all
def tell(*players, message, with_tag=True, **tokens):
"""Send a SayText2 message to players"""
player_indexes = [player.index for player in players]
base = strings['chat base with_tag' if with_tag else 'chat base']
tokenized_message = base.tokenize(
tag=strings['tag'].tokenize(
**color_tokens # Tag only needs color tokens
),
text=message.tokenize(
**color_tokens, # Message needs color tokens
**tokens # But it also needs tokens passed to tell()
),
colorful_sign=COLORFUL_SIGN, # The base needs this symbol
)
# Note how we don't pass any tokens in .send()
SayText2(message=tokenized_message).send(*player_indexes)
Finally, let's use all of that
Syntax: Select all
@Event('player_spawn')
def on_player_spawn(game_event):
player = Player(index_from_userid(game_event.get_int('userid')))
# Let tell() pack all additional tokens ('team' in our case) by itself
tell(player, message=strings['your_team_is'], team=strings['team_alpha'])
# Or pack such tokens by ourselves - the previous approach is shorter
tell(player, message=strings['your_team_is'].tokenize(team=strings['team_bravo']))
# Also send a popup
popup.send(player.index)
Result:

The package can be found here
Sample plugin is all given above, the one thing is that here's working Python 3.4 version of tell():
Syntax: Select all
def tell(*players, message, with_tag=True, **tokens):
"""Send a SayText2 message to players"""
player_indexes = [player.index for player in players]
base = strings['chat base with_tag' if with_tag else 'chat base']
tokens.update(color_tokens)
tokenized_message = base.tokenize(
tag=strings['tag'].tokenize(
**color_tokens # Tag only needs color tokens
),
text=message.tokenize(
**tokens
),
colorful_sign=COLORFUL_SIGN, # The base needs this
)
SayText2(message=tokenized_message).send(*player_indexes)
I hope some ideas of this package can make their way into Source.Python. Thanks.