Compare commits

...

142 Commits

Author SHA1 Message Date
1348d42bb1
Merge "origin/master" into "philip/clean-up" 2022-01-04 19:10:34 +03:00
b43d9618d9
Addresses remaining bullets in hardening issue. 2021-12-29 17:18:17 +03:00
55266fd721
Adds system guardians 2021-12-29 17:17:13 +03:00
6aa836b1d2
Integrates translation management. 2021-12-29 17:16:41 +03:00
9b639c4ea9
Adds ability to temporarily cache language selection upon account creation. 2021-12-29 17:15:28 +03:00
54c9fe34ce
Retires old translation files. 2021-12-29 17:14:24 +03:00
599c01931e
Makes language list dynamic-ish. 2021-12-29 17:13:57 +03:00
c2c7eb5e6d
Adds ability to select language before creating account. 2021-12-29 17:10:25 +03:00
nolash
7618abcda3
Bump deps 2021-12-22 21:31:39 +00:00
nolash
94d8ddb164
Amend okota dependency conflict 2021-12-22 20:34:12 +00:00
nolash
7f958d4be8
Rehabiliate test for balance incoming check (already counted from PENDING state) 2021-12-22 20:23:02 +00:00
nolash
03b06ca8c1 Merge remote-tracking branch 'origin/master' into lash/improve-cache 2021-12-22 20:09:54 +00:00
nolash
14449f5c6d
Rehabilitate tests for cic-eth 2021-12-22 20:02:05 +00:00
nolash
15618fa061
Rehabilitate tests after url format change 2021-12-22 19:12:08 +00:00
nolash
3a52a78e93
Change poker method 2021-12-21 14:23:33 +00:00
nolash
6562d37a30
Add demurrage poker script 2021-12-21 14:19:26 +00:00
nolash
c5efa56885
Loosen requirements restrictions, fix missing explicit nonce in global contract deploy last step 2021-12-21 14:18:09 +00:00
d6346bb87b
Merge "origin/master" into "lash/improve-cache" 2021-12-20 11:14:04 +03:00
9050d331cd
Bumps lib versions 2021-12-20 11:12:39 +03:00
99997df248
Bumps deps 2021-12-20 11:11:23 +03:00
d04a4bf5c6
Adds missing import: tempfile 2021-12-20 11:10:35 +03:00
43c49dd527
Adds minor fixes:
- Added appropriate imports:
  - from okota.token_index.index import to_identifier
  - from cic_eth.error import SignerError
- cleaned up balance func.
2021-12-20 11:07:41 +03:00
511557c242
Cleaned up docker-compose.yml:
- Added ETH_MIN_FEE_LIMIT.
- Removed "" from callback task definitions.
2021-12-20 11:03:23 +03:00
887799962f
Couldn't get python setup.py install to work without it fussing:
```
 => => # Processing dependencies for cic-cache==0.3.1
 => => # Searching for eth-contract-registry~=0.7.1a2
 => => # Reading https://pypi.org/simple/eth-contract-registry/
 => => # Couldn't retrieve index page for 'eth-contract-registry'
 => => # Scanning index of all packages (this may take a while)
 => => # Reading https://pypi.org/simple/
```
2021-12-20 11:01:39 +03:00
3acc3cf417
Bumps deps. 2021-12-20 10:58:21 +03:00
ceeb246ce2
Retires unused override_requirements.txt file. 2021-12-20 10:56:30 +03:00
45499ec839
Refactor to match proof checked for by verify_proofs task. 2021-12-20 10:56:01 +03:00
77bdee049c
Adds token decimals to demurrage token deployment. 2021-12-20 10:54:28 +03:00
nolash
0cf6489f49 Merge remote-tracking branch 'origin/master' into lash/improve-cache 2021-12-08 06:44:31 +01:00
nolash
31256b3650
Remove custom port in pip url in dockers 2021-12-07 21:54:04 +01:00
nolash
380550cb84
Add higher fee limit in base task 2021-12-07 21:45:07 +01:00
nolash
a356585c6a
Remove port from pip 2021-12-06 17:45:44 +01:00
nolash
4809bc8c22
Bump confini 2021-12-06 14:21:26 +01:00
nolash
760f618943
WIP upgrade deps 2021-12-04 11:39:13 +01:00
nolash
39de1837c2
Upgrade deps to non-prerelease (temporarily removed transfer-auth) 2021-11-15 14:23:24 +01:00
nolash
97e45c87d7
WIP move to whole patch versions in deps 2021-11-15 14:07:54 +01:00
nolash
4658a5d8e5
Bump cic-cache version 2021-11-13 07:51:01 +01:00
nolash
995d4e0bd0
Add remaining database name prefix changes 2021-11-10 09:55:30 +01:00
nolash
140b72a72b
Use database prefix instead of name 2021-11-10 09:07:23 +01:00
nolash
21b0c4a48b
Change query parse order 2021-11-08 09:58:22 +01:00
nolash
0b66462c11
Update openapi spec, enable queries with no ranges 2021-11-04 09:42:35 +01:00
nolash
f18f865231
WIP openapi spec for cic-cache-server 2021-11-04 07:59:38 +01:00
nolash
ad1c241a85
Reorganize url path params in cic-cache-server 2021-11-04 06:06:34 +01:00
nolash
99b0fb5aed Merge branch 'lash/verify-cache' into lash/bloxberg-seeding 2021-11-04 04:26:50 +01:00
nolash
29423449b7 Merge remote-tracking branch 'origin/master' into lash/verify-cache 2021-11-04 04:23:47 +01:00
nolash
58e766aa58
Remove explicit config in db migration 2021-11-04 04:18:27 +01:00
nolash
2ebcd3e3de Merge remote-tracking branch 'origin/master' into lash/bloxberg-seeding 2021-11-02 18:49:49 +01:00
nolash
c440b049cc
Add config dirs 2021-11-02 16:35:44 +01:00
nolash
09034af5bc
Bump cic-eth version 2021-11-02 16:03:29 +01:00
nolash
dc80bae673
Upgrade cic-eth in migrations 2021-11-02 15:31:00 +01:00
nolash
d88ae00b72
Add celery cli args with defaults from redis 2021-10-31 07:58:35 +01:00
nolash
7a366edb9d
WIP rehabilitate cic-eth-inspect 2021-10-30 19:09:17 +02:00
nolash
0b912b99b6
Add role listing to cic-eth tag cli tool 2021-10-30 13:19:31 +02:00
nolash
cbd4aef004
Add action confirm on sweep script 2021-10-30 10:25:39 +02:00
nolash
6f7f91780b
Add script to sweep gas from signer accounts 2021-10-30 09:02:04 +02:00
nolash
83ecdaf023
Connect token filter to tracker 2021-10-29 16:35:11 +02:00
nolash
e2ef9b43c8
Reactivate cic-eth-tasker dependency for bootstrap 2021-10-29 15:58:34 +02:00
nolash
6e58e4e4de
Remove nasty residue from bootstrap 2021-10-29 14:40:06 +02:00
nolash
f46c9b0e7d Merge remote-tracking branch 'origin/master' into lash/bloxberg-seeding 2021-10-29 11:39:40 +02:00
nolash
6ca3fd55d7
Add gas cache oracle connection for erc20 2021-10-29 08:45:42 +02:00
nolash
258ed420b8 Merge branch 'lash/tmp-bloxberg-seeding' into lash/bloxberg-seeding 2021-10-29 07:35:08 +02:00
nolash
1c022e9853
Added changes to wrong branch 2021-10-29 07:33:38 +02:00
nolash
d35e144723
Register gas cache only for registered tokens 2021-10-29 07:00:25 +02:00
nolash
fb953d0318
Add gas cache backend, test, filter 2021-10-28 21:45:47 +02:00
nolash
858bbdb69a Merge remote-tracking branch 'origin/master' into lash/local-dev-improve 2021-10-28 14:36:45 +02:00
nolash
66e23e4e20
Test config cleanup 2021-10-28 14:11:11 +02:00
nolash
546256c86a
Better gas gifting amounts and thresholds estimation, fix broken cic-eth imports 2021-10-28 13:34:39 +02:00
nolash
d9720bd0aa Merge remote-tracking branch 'origin/lash/local-dev-improve' into lash/bloxberg-seeding 2021-10-28 05:41:27 +02:00
nolash
e9e9f66d97
Correct wrong change for docker registries 2021-10-28 05:39:44 +02:00
nolash
0d640fab57 Merge remote-tracking branch 'origin/lash/local-dev-improve' into lash/bloxberg-seeding 2021-10-28 05:29:07 +02:00
nolash
4ce85bc824
Remove faulty default registry in dockerfiles 2021-10-28 05:27:13 +02:00
nolash
ce67f83457
Remove faulty default registry in docker compose 2021-10-28 05:24:11 +02:00
nolash
13f2e17931
Remove accidental 0 value override for syncer offset to trackers 2021-10-28 05:18:54 +02:00
nolash
f236234682 Merge remote-tracking branch 'origin/master' into lash/local-dev-improve 2021-10-27 16:58:38 +02:00
nolash
1f37632f0f
WIP Replace env vars in data-seeding with well-known 2021-10-27 16:56:03 +02:00
nolash
03d7518f8c Merge branch 'lash/local-dev-improve' of gitlab.com:grassrootseconomics/cic-internal-integration into lash/local-dev-improve 2021-10-27 11:52:31 +02:00
nolash
67152d0df1
Replace KEYSTORE_PATH with WALLET_KEY_FILE in data seeding 2021-10-27 11:51:20 +02:00
9168322941
Revert base image changes. 2021-10-27 12:41:35 +03:00
2fbd338e24
Adds correct base image. 2021-10-27 11:44:23 +03:00
c7d7f2a64d
Remove force reset. 2021-10-27 11:44:08 +03:00
16153df2f0
Resolve creation of phone dir when it already exists. 2021-10-27 11:43:35 +03:00
nolash
4391fa3aff Merge remote-tracking branch 'origin/master' into lash/local-dev-improve 2021-10-25 21:01:27 +02:00
nolash
7ce68021bd Merge remote-tracking branch 'origin/master' into lash/verify-cache 2021-10-25 20:20:40 +02:00
nolash
cd602dee49
Remove WIP docker compose file 2021-10-25 20:12:32 +02:00
nolash
a548ba6fce
Chainlib upgrade to handle none receipts, rpc node debug output in bootstrap 2021-10-25 20:09:35 +02:00
nolash
a6de7e9fe0 Merge remote-tracking branch 'origin/master' into lash/local-dev-improve 2021-10-20 20:02:19 +02:00
nolash
e705a94873
Resolve notify/ussd dependency conflict 2021-10-20 10:07:19 +02:00
nolash
3923de0a81
Update pip args handling in notify 2021-10-19 23:01:55 +02:00
nolash
5c0250b5b9
Rehabilitate cic-cache db migration 2021-10-19 22:58:10 +02:00
nolash
3285d8dfe5
Implement asynchronous deploys in bootstrap 2021-10-19 22:08:17 +02:00
nolash
9d349f1579
Add debug level env var to bootstrap dev container 2021-10-19 19:54:59 +02:00
nolash
837a1770d1
Upgrade deps more chainlib in bootstrap 2021-10-19 10:10:39 +02:00
003febec9d
Bumps contract migration deps. 2021-10-19 10:38:21 +03:00
f066a32ce8
Adds libffi-dev for local git-tea. 2021-10-19 10:38:08 +03:00
nolash
ad493705ad
Upgrade deps 2021-10-18 17:16:28 +02:00
nolash
b765c4ab88
More wrestling with chainlib-eth deps 2021-10-18 17:06:31 +02:00
nolash
e4935d3b58 Merge branch 'lash/split-migration' of gitlab.com:grassrootseconomics/cic-internal-integration into lash/split-migration 2021-10-18 16:49:58 +02:00
nolash
f88f0e321b
Upgrade chainlib-eth dep 2021-10-18 16:48:14 +02:00
31fa721397
Add cic-notify container 2021-10-18 17:17:53 +03:00
16481da193
Merge remote-tracking branch 'origin/lash/split-migration' into lash/split-migration 2021-10-18 16:54:23 +03:00
97a48cd8c6
Improves ussd deps. 2021-10-18 16:53:38 +03:00
nolash
7732412341 Merge branch 'lash/split-migration' of gitlab.com:grassrootseconomics/cic-internal-integration into lash/split-migration 2021-10-18 15:51:38 +02:00
nolash
649b124a61
Ugprade chainqueue dep 2021-10-18 15:50:45 +02:00
7601e3eeff
Corrects breakages in cic-ussd 2021-10-18 15:19:32 +03:00
60a9efc88b
Merge remote-tracking branch 'origin/lash/split-migration' into lash/split-migration 2021-10-18 15:18:33 +03:00
45011b58c4
Cleans up configs. 2021-10-18 15:11:31 +03:00
nolash
f1a0b4ee7c Merge branch 'lash/split-migration' of gitlab.com:grassrootseconomics/cic-internal-integration into lash/split-migration 2021-10-18 14:10:52 +02:00
nolash
c57abb7ad5
Upgrade deps in cic-eth, allow for new chain spec format 2021-10-18 14:08:39 +02:00
930a99c974
Bumps cic-types version. 2021-10-18 06:52:49 +03:00
b0935caab8
Fixes imports. 2021-10-18 06:52:28 +03:00
nolash
bdd5f6fcec
Update readme in data seeding 2021-10-17 19:37:29 +02:00
nolash
a293c2460e
Consolidate dir handling in data seeding scripts 2021-10-17 19:27:15 +02:00
nolash
0ee6400d7d
WIP rehabilitate ussd builds 2021-10-17 18:32:08 +02:00
nolash
677fb346fd
Add data seeding preparation step, rehabilitation of non-custodial seeding 2021-10-17 18:05:00 +02:00
nolash
ea3c75e755
Rehabilitate traffic script 2021-10-17 14:30:42 +02:00
nolash
0b2f22c416
Rehabilitate cic-user-server 2021-10-16 20:54:41 +02:00
nolash
24385ea27d
Rehabilitate cic-cache 2021-10-16 14:03:05 +02:00
nolash
9a154a8046
WIP rehabilitate cic-cache 2021-10-16 08:23:32 +02:00
nolash
d3576c8ec7
Add eth retrier to new docker compose file 2021-10-16 07:08:44 +02:00
nolash
79ee2bf4ff
Add eth tracker, dispatcher to new docker compose file 2021-10-16 07:04:19 +02:00
nolash
89ac70371a
Remove single function worker in test 2021-10-16 00:18:08 +02:00
nolash
5ea0318b0b
Fix default token symbol config setting for aux 2021-10-15 23:21:57 +02:00
nolash
5dfb96ec0c
Add new cic-signer app 2021-10-15 23:11:00 +02:00
nolash
4634ac41df Merge remote-tracking branch 'origin/master' into lash/split-migration 2021-10-15 22:19:01 +02:00
nolash
97f4fe8ca7
refactor docker-compose cic-eth-tasker, bootstrap (aka contract migration) 2021-10-15 22:16:45 +02:00
nolash
b36529f7fa
WIP local docker registry adaptations 2021-10-15 20:27:03 +02:00
nolash
a6675f2348
Add environment sourcing for cic-eth-tasker docker compose 2021-10-15 18:52:37 +02:00
nolash
e3116d74d6
No export 2021-10-15 12:54:16 +02:00
nolash
c0bbdc9bec
Add missing file 2021-10-15 08:43:04 +02:00
nolash
396bd4f300
update preliminary readme 2021-10-15 08:38:01 +02:00
nolash
58547b4067
Bump cic-eth-registry 2021-10-15 07:44:50 +02:00
nolash
9009815d78
Add trust address to contract migration config, get cic-eth default token from registry 2021-10-14 21:31:04 +02:00
nolash
2da19f5819
Add basic connectivity config directives 2021-10-14 17:40:53 +02:00
nolash
3948d5aa40
Add custodial initialization 2021-10-14 17:18:49 +02:00
nolash
ed432abb23
WIP refactor custodial initialization 2021-10-14 14:37:48 +02:00
nolash
f251b8b729
Remove dead code 2021-10-14 11:35:08 +02:00
nolash
36e791e08a
Split contract migration into three separate steps 2021-10-14 11:33:50 +02:00
nolash
71a7e3d3d5
Reinstate test config dir 2021-10-09 17:23:38 +02:00
nolash
335b7b30a4
Add okota dep 2021-10-09 16:40:28 +02:00
nolash
3b1f470ddf
Add empty config dir 2021-10-09 16:33:40 +02:00
nolash
4c9f20aa7f
Add explicit zero length tx lsit check for cic-cache verify 2021-10-08 11:26:09 +02:00
nolash
980191be4f
Add verify check for cache, use chainlib cli for cic-cache 2021-10-08 11:19:21 +02:00
40 changed files with 1582 additions and 1024 deletions

View File

@ -0,0 +1,22 @@
# standard imports
# external imports
# local imports
class Guardianship:
guardians: list = []
@classmethod
def load_system_guardians(cls, guardians_file: str):
with open(guardians_file, 'r') as system_guardians:
cls.guardians = [line.strip() for line in system_guardians]
def is_system_guardian(self, phone_number: str):
"""
:param phone_number:
:type phone_number:
:return:
:rtype:
"""
return phone_number in self.guardians

View File

@ -13,7 +13,6 @@ from cic_types.condiments import MetadataPointer
from cic_ussd.account.chain import Chain from cic_ussd.account.chain import Chain
from cic_ussd.account.transaction import from_wei from cic_ussd.account.transaction import from_wei
from cic_ussd.cache import cache_data_key, get_cached_data from cic_ussd.cache import cache_data_key, get_cached_data
from cic_ussd.translation import translation_for
logg = logging.getLogger(__name__) logg = logging.getLogger(__name__)
@ -97,17 +96,3 @@ def query_statement(blockchain_address: str, limit: int = 9):
callback_param=blockchain_address callback_param=blockchain_address
) )
cic_eth_api.list(address=blockchain_address, limit=limit) cic_eth_api.list(address=blockchain_address, limit=limit)
def statement_transaction_set(preferred_language: str, transaction_reprs: list):
"""
:param preferred_language:
:type preferred_language:
:param transaction_reprs:
:type transaction_reprs:
:return:
:rtype:
"""
if not transaction_reprs:
return translation_for('helpers.no_transaction_history', preferred_language)
return ''.join(f'{transaction_repr}\n' for transaction_repr in transaction_reprs)

View File

@ -15,7 +15,6 @@ from cic_ussd.cache import cache_data, cache_data_key, get_cached_data
from cic_ussd.error import CachedDataNotFoundError, SeppukuError from cic_ussd.error import CachedDataNotFoundError, SeppukuError
from cic_ussd.metadata.tokens import query_token_info, query_token_metadata from cic_ussd.metadata.tokens import query_token_info, query_token_metadata
from cic_ussd.processor.util import wait_for_cache from cic_ussd.processor.util import wait_for_cache
from cic_ussd.translation import translation_for
logg = logging.getLogger(__file__) logg = logging.getLogger(__file__)
@ -326,16 +325,3 @@ def set_active_token(blockchain_address: str, token_symbol: str):
cache_data(key=key, data=token_symbol) cache_data(key=key, data=token_symbol)
def token_list_set(preferred_language: str, token_data_reprs: list):
"""
:param preferred_language:
:type preferred_language:
:param token_data_reprs:
:type token_data_reprs:
:return:
:rtype:
"""
if not token_data_reprs:
return translation_for('helpers.no_tokens_list', preferred_language)
return ''.join(f'{token_data_repr}\n' for token_data_repr in token_data_reprs)

View File

@ -55,5 +55,6 @@ def cache_data_key(identifier: Union[list, bytes], salt: MetadataPointer):
hash_object.update(identity) hash_object.update(identity)
else: else:
hash_object.update(identifier) hash_object.update(identifier)
if salt != MetadataPointer.NONE:
hash_object.update(salt.value.encode(encoding="utf-8")) hash_object.update(salt.value.encode(encoding="utf-8"))
return hash_object.digest().hex() return hash_object.digest().hex()

View File

@ -171,7 +171,7 @@ class Account(SessionBase):
return check_password_hash(password, self.password_hash) return check_password_hash(password, self.password_hash)
def create(chain_str: str, phone_number: str, session: Session): def create(chain_str: str, phone_number: str, session: Session, preferred_language: str):
""" """
:param chain_str: :param chain_str:
:type chain_str: :type chain_str:
@ -179,12 +179,14 @@ def create(chain_str: str, phone_number: str, session: Session):
:type phone_number: :type phone_number:
:param session: :param session:
:type session: :type session:
:param preferred_language:
:type preferred_language:
:return: :return:
:rtype: :rtype:
""" """
api = Api(callback_task='cic_ussd.tasks.callback_handler.account_creation_callback', api = Api(callback_task='cic_ussd.tasks.callback_handler.account_creation_callback',
callback_queue='cic-ussd', callback_queue='cic-ussd',
callback_param='', callback_param=preferred_language,
chain_str=chain_str) chain_str=chain_str)
task_uuid = api.create_account().id task_uuid = api.create_account().id
TaskTracker.add(session=session, task_uuid=task_uuid) TaskTracker.add(session=session, task_uuid=task_uuid)

View File

@ -2,417 +2,441 @@
"ussd_menu": { "ussd_menu": {
"1": { "1": {
"description": "Entry point for users to select their preferred language.", "description": "Entry point for users to select their preferred language.",
"display_key": "ussd.kenya.initial_language_selection", "display_key": "ussd.initial_language_selection",
"name": "initial_language_selection", "name": "initial_language_selection",
"parent": null "parent": null
}, },
"2": { "2": {
"description": "Entry point for users to enter a pin to secure their account.", "description": "Entry point for users to enter a pin to secure their account.",
"display_key": "ussd.kenya.initial_pin_entry", "display_key": "ussd.initial_pin_entry",
"name": "initial_pin_entry", "name": "initial_pin_entry",
"parent": null "parent": null
}, },
"3": { "3": {
"description": "Pin confirmation entry menu.", "description": "Pin confirmation entry menu.",
"display_key": "ussd.kenya.initial_pin_confirmation", "display_key": "ussd.initial_pin_confirmation",
"name": "initial_pin_confirmation", "name": "initial_pin_confirmation",
"parent": "initial_pin_entry" "parent": "initial_pin_entry"
}, },
"4": { "4": {
"description": "The signup process has been initiated and the account is being created.", "description": "The signup process has been initiated and the account is being created.",
"display_key": "ussd.kenya.account_creation_prompt", "display_key": "ussd.account_creation_prompt",
"name": "account_creation_prompt", "name": "account_creation_prompt",
"parent": null "parent": null
}, },
"5": { "5": {
"description": "Entry point for activated users.", "description": "Entry point for activated users.",
"display_key": "ussd.kenya.start", "display_key": "ussd.start",
"name": "start", "name": "start",
"parent": null "parent": null
}, },
"6": { "6": {
"description": "Given name entry menu.", "description": "Given name entry menu.",
"display_key": "ussd.kenya.enter_given_name", "display_key": "ussd.enter_given_name",
"name": "enter_given_name", "name": "enter_given_name",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"7": { "7": {
"description": "Family name entry menu.", "description": "Family name entry menu.",
"display_key": "ussd.kenya.enter_family_name", "display_key": "ussd.enter_family_name",
"name": "enter_family_name", "name": "enter_family_name",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"8": { "8": {
"description": "Gender entry menu.", "description": "Gender entry menu.",
"display_key": "ussd.kenya.enter_gender", "display_key": "ussd.enter_gender",
"name": "enter_gender", "name": "enter_gender",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"9": { "9": {
"description": "Age entry menu.", "description": "Age entry menu.",
"display_key": "ussd.kenya.enter_gender", "display_key": "ussd.enter_gender",
"name": "enter_gender", "name": "enter_gender",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"10": { "10": {
"description": "Location entry menu.", "description": "Location entry menu.",
"display_key": "ussd.kenya.enter_location", "display_key": "ussd.enter_location",
"name": "enter_location", "name": "enter_location",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"11": { "11": {
"description": "Products entry menu.", "description": "Products entry menu.",
"display_key": "ussd.kenya.enter_products", "display_key": "ussd.enter_products",
"name": "enter_products", "name": "enter_products",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"12": { "12": {
"description": "Entry point for activated users.", "description": "Entry point for activated users.",
"display_key": "ussd.kenya.start", "display_key": "ussd.start",
"name": "start", "name": "start",
"parent": null "parent": null
}, },
"13": { "13": {
"description": "Send Token recipient entry.", "description": "Send Token recipient entry.",
"display_key": "ussd.kenya.enter_transaction_recipient", "display_key": "ussd.enter_transaction_recipient",
"name": "enter_transaction_recipient", "name": "enter_transaction_recipient",
"parent": "start" "parent": "start"
}, },
"14": { "14": {
"description": "Send Token amount prompt menu.", "description": "Send Token amount prompt menu.",
"display_key": "ussd.kenya.enter_transaction_amount", "display_key": "ussd.enter_transaction_amount",
"name": "enter_transaction_amount", "name": "enter_transaction_amount",
"parent": "start" "parent": "start"
}, },
"15": { "15": {
"description": "Pin entry for authorization to send token.", "description": "Pin entry for authorization to send token.",
"display_key": "ussd.kenya.transaction_pin_authorization", "display_key": "ussd.transaction_pin_authorization",
"name": "transaction_pin_authorization", "name": "transaction_pin_authorization",
"parent": "start" "parent": "start"
}, },
"16": { "16": {
"description": "Manage account menu.", "description": "Manage account menu.",
"display_key": "ussd.kenya.account_management", "display_key": "ussd.account_management",
"name": "account_management", "name": "account_management",
"parent": "start" "parent": "start"
}, },
"17": { "17": {
"description": "Manage metadata menu.", "description": "Manage metadata menu.",
"display_key": "ussd.kenya.metadata_management", "display_key": "ussd.metadata_management",
"name": "metadata_management", "name": "metadata_management",
"parent": "start" "parent": "start"
}, },
"18": { "18": {
"description": "Manage user's preferred language menu.", "description": "Manage user's preferred language menu.",
"display_key": "ussd.kenya.select_preferred_language", "display_key": "ussd.select_preferred_language",
"name": "select_preferred_language", "name": "select_preferred_language",
"parent": "account_management" "parent": "account_management"
}, },
"19": { "19": {
"description": "Retrieve mini-statement menu.", "description": "Retrieve mini-statement menu.",
"display_key": "ussd.kenya.mini_statement_pin_authorization", "display_key": "ussd.mini_statement_pin_authorization",
"name": "mini_statement_pin_authorization", "name": "mini_statement_pin_authorization",
"parent": "account_management" "parent": "account_management"
}, },
"20": { "20": {
"description": "Manage user's pin menu.", "description": "Manage user's pin menu.",
"display_key": "ussd.kenya.enter_current_pin", "display_key": "ussd.enter_current_pin",
"name": "enter_current_pin", "name": "enter_current_pin",
"parent": "account_management" "parent": "account_management"
}, },
"21": { "21": {
"description": "New pin entry menu.", "description": "New pin entry menu.",
"display_key": "ussd.kenya.enter_new_pin", "display_key": "ussd.enter_new_pin",
"name": "enter_new_pin", "name": "enter_new_pin",
"parent": "account_management" "parent": "account_management"
}, },
"22": { "22": {
"description": "Pin entry menu.", "description": "Pin entry menu.",
"display_key": "ussd.kenya.display_metadata_pin_authorization", "display_key": "ussd.display_metadata_pin_authorization",
"name": "display_metadata_pin_authorization", "name": "display_metadata_pin_authorization",
"parent": "start" "parent": "start"
}, },
"23": { "23": {
"description": "Exit menu.", "description": "Exit menu.",
"display_key": "ussd.kenya.exit", "display_key": "ussd.exit",
"name": "exit", "name": "exit",
"parent": null "parent": null
}, },
"24": { "24": {
"description": "Invalid menu option.", "description": "Invalid menu option.",
"display_key": "ussd.kenya.exit_invalid_menu_option", "display_key": "ussd.exit_invalid_menu_option",
"name": "exit_invalid_menu_option", "name": "exit_invalid_menu_option",
"parent": null "parent": null
}, },
"25": { "25": {
"description": "Pin policy violation.", "description": "Pin policy violation.",
"display_key": "ussd.kenya.exit_invalid_pin", "display_key": "ussd.exit_invalid_pin",
"name": "exit_invalid_pin", "name": "exit_invalid_pin",
"parent": null "parent": null
}, },
"26": { "26": {
"description": "Pin mismatch. New pin and the new pin confirmation do not match", "description": "Pin mismatch. New pin and the new pin confirmation do not match",
"display_key": "ussd.kenya.exit_pin_mismatch", "display_key": "ussd.exit_pin_mismatch",
"name": "exit_pin_mismatch", "name": "exit_pin_mismatch",
"parent": null "parent": null
}, },
"27": { "27": {
"description": "Ussd pin blocked Menu", "description": "Ussd pin blocked Menu",
"display_key": "ussd.kenya.exit_pin_blocked", "display_key": "ussd.exit_pin_blocked",
"name": "exit_pin_blocked", "name": "exit_pin_blocked",
"parent": null "parent": null
}, },
"28": { "28": {
"description": "Key params missing in request.", "description": "Key params missing in request.",
"display_key": "ussd.kenya.exit_invalid_request", "display_key": "ussd.exit_invalid_request",
"name": "exit_invalid_request", "name": "exit_invalid_request",
"parent": null "parent": null
}, },
"29": { "29": {
"description": "The user did not select a choice.", "description": "The user did not select a choice.",
"display_key": "ussd.kenya.exit_invalid_input", "display_key": "ussd.exit_invalid_input",
"name": "exit_invalid_input", "name": "exit_invalid_input",
"parent": null "parent": null
}, },
"30": { "30": {
"description": "Exit following unsuccessful transaction due to insufficient account balance.", "description": "Exit following unsuccessful transaction due to insufficient account balance.",
"display_key": "ussd.kenya.exit_insufficient_balance", "display_key": "ussd.exit_insufficient_balance",
"name": "exit_insufficient_balance", "name": "exit_insufficient_balance",
"parent": null "parent": null
}, },
"31": { "31": {
"description": "Exit following a successful transaction.", "description": "Exit following a successful transaction.",
"display_key": "ussd.kenya.exit_successful_transaction", "display_key": "ussd.exit_successful_transaction",
"name": "exit_successful_transaction", "name": "exit_successful_transaction",
"parent": null "parent": null
}, },
"32": { "32": {
"description": "End of a menu flow.", "description": "End of a menu flow.",
"display_key": "ussd.kenya.complete", "display_key": "ussd.complete",
"name": "complete", "name": "complete",
"parent": null "parent": null
}, },
"33": { "33": {
"description": "Pin entry menu to view account balances.", "description": "Pin entry menu to view account balances.",
"display_key": "ussd.kenya.account_balances_pin_authorization", "display_key": "ussd.account_balances_pin_authorization",
"name": "account_balances_pin_authorization", "name": "account_balances_pin_authorization",
"parent": "account_management" "parent": "account_management"
}, },
"34": { "34": {
"description": "Pin entry menu to view account statement.", "description": "Pin entry menu to view account statement.",
"display_key": "ussd.kenya.account_statement_pin_authorization", "display_key": "ussd.account_statement_pin_authorization",
"name": "account_statement_pin_authorization", "name": "account_statement_pin_authorization",
"parent": "account_management" "parent": "account_management"
}, },
"35": { "35": {
"description": "Menu to display account balances.", "description": "Menu to display account balances.",
"display_key": "ussd.kenya.account_balances", "display_key": "ussd.account_balances",
"name": "account_balances", "name": "account_balances",
"parent": "account_management" "parent": "account_management"
}, },
"36": { "36": {
"description": "Menu to display first set of transactions in statement.", "description": "Menu to display first set of transactions in statement.",
"display_key": "ussd.kenya.first_transaction_set", "display_key": "ussd.first_transaction_set",
"name": "first_transaction_set", "name": "first_transaction_set",
"parent": null "parent": "account_management"
}, },
"37": { "37": {
"description": "Menu to display middle set of transactions in statement.", "description": "Menu to display middle set of transactions in statement.",
"display_key": "ussd.kenya.middle_transaction_set", "display_key": "ussd.middle_transaction_set",
"name": "middle_transaction_set", "name": "middle_transaction_set",
"parent": null "parent": null
}, },
"38": { "38": {
"description": "Menu to display last set of transactions in statement.", "description": "Menu to display last set of transactions in statement.",
"display_key": "ussd.kenya.last_transaction_set", "display_key": "ussd.last_transaction_set",
"name": "last_transaction_set", "name": "last_transaction_set",
"parent": null "parent": null
}, },
"39": { "39": {
"description": "Menu to instruct users to call the office.", "description": "Menu to instruct users to call the office.",
"display_key": "ussd.kenya.help", "display_key": "ussd.help",
"name": "help", "name": "help",
"parent": null "parent": null
}, },
"40": { "40": {
"description": "Menu to display a user's entire profile", "description": "Menu to display a user's entire profile",
"display_key": "ussd.kenya.display_user_metadata", "display_key": "ussd.display_user_metadata",
"name": "display_user_metadata", "name": "display_user_metadata",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"41": { "41": {
"description": "The recipient is not in the system", "description": "The recipient is not in the system",
"display_key": "ussd.kenya.exit_invalid_recipient", "display_key": "ussd.exit_invalid_recipient",
"name": "exit_invalid_recipient", "name": "exit_invalid_recipient",
"parent": null "parent": null
}, },
"42": { "42": {
"description": "Pin entry menu for changing name data.", "description": "Pin entry menu for changing name data.",
"display_key": "ussd.kenya.name_edit_pin_authorization", "display_key": "ussd.name_edit_pin_authorization",
"name": "name_edit_pin_authorization", "name": "name_edit_pin_authorization",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"43": { "43": {
"description": "Pin entry menu for changing gender data.", "description": "Pin entry menu for changing gender data.",
"display_key": "ussd.kenya.gender_edit_pin_authorization", "display_key": "ussd.gender_edit_pin_authorization",
"name": "gender_edit_pin_authorization", "name": "gender_edit_pin_authorization",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"44": { "44": {
"description": "Pin entry menu for changing location data.", "description": "Pin entry menu for changing location data.",
"display_key": "ussd.kenya.location_edit_pin_authorization", "display_key": "ussd.location_edit_pin_authorization",
"name": "location_edit_pin_authorization", "name": "location_edit_pin_authorization",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"45": { "45": {
"description": "Pin entry menu for changing products data.", "description": "Pin entry menu for changing products data.",
"display_key": "ussd.kenya.products_edit_pin_authorization", "display_key": "ussd.products_edit_pin_authorization",
"name": "products_edit_pin_authorization", "name": "products_edit_pin_authorization",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"46": { "46": {
"description": "Pin confirmation for pin change.", "description": "Pin confirmation for pin change.",
"display_key": "ussd.kenya.new_pin_confirmation", "display_key": "ussd.new_pin_confirmation",
"name": "new_pin_confirmation", "name": "new_pin_confirmation",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"47": { "47": {
"description": "Year of birth entry menu.", "description": "Year of birth entry menu.",
"display_key": "ussd.kenya.enter_date_of_birth", "display_key": "ussd.enter_date_of_birth",
"name": "enter_date_of_birth", "name": "enter_date_of_birth",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"48": { "48": {
"description": "Pin entry menu for changing year of birth data.", "description": "Pin entry menu for changing year of birth data.",
"display_key": "ussd.kenya.dob_edit_pin_authorization", "display_key": "ussd.dob_edit_pin_authorization",
"name": "dob_edit_pin_authorization", "name": "dob_edit_pin_authorization",
"parent": "metadata_management" "parent": "metadata_management"
}, },
"49": { "49": {
"description": "Menu to display first set of tokens in the account's token list.", "description": "Menu to display first set of tokens in the account's token list.",
"display_key": "ussd.kenya.first_account_tokens_set", "display_key": "ussd.first_account_tokens_set",
"name": "first_account_tokens_set", "name": "first_account_tokens_set",
"parent": null "parent": "start"
}, },
"50": { "50": {
"description": "Menu to display middle set of tokens in the account's token list.", "description": "Menu to display middle set of tokens in the account's token list.",
"display_key": "ussd.kenya.middle_account_tokens_set", "display_key": "ussd.middle_account_tokens_set",
"name": "middle_account_tokens_set", "name": "middle_account_tokens_set",
"parent": null "parent": null
}, },
"51": { "51": {
"description": "Menu to display last set of tokens in the account's token list.", "description": "Menu to display last set of tokens in the account's token list.",
"display_key": "ussd.kenya.last_account_tokens_set", "display_key": "ussd.last_account_tokens_set",
"name": "last_account_tokens_set", "name": "last_account_tokens_set",
"parent": null "parent": null
}, },
"52": { "52": {
"description": "Pin entry menu for setting an active token.", "description": "Pin entry menu for setting an active token.",
"display_key": "ussd.kenya.token_selection_pin_authorization", "display_key": "ussd.token_selection_pin_authorization",
"name": "token_selection_pin_authorization", "name": "token_selection_pin_authorization",
"parent": null "parent": "first_account_tokens_set"
}, },
"53": { "53": {
"description": "Exit following a successful active token setting.", "description": "Exit following a successful active token setting.",
"display_key": "ussd.kenya.exit_successful_token_selection", "display_key": "ussd.exit_successful_token_selection",
"name": "exit_successful_token_selection", "name": "exit_successful_token_selection",
"parent": null "parent": null
}, },
"54": { "54": {
"description": "Pin management menu for operations related to an account's pin.", "description": "Pin management menu for operations related to an account's pin.",
"display_key": "ussd.kenya.pin_management", "display_key": "ussd.pin_management",
"name": "pin_management", "name": "pin_management",
"parent": "start" "parent": "start"
}, },
"55": { "55": {
"description": "Phone number entry for account whose pin is being reset.", "description": "Phone number entry for account whose pin is being reset.",
"display_key": "ussd.kenya.reset_guarded_pin", "display_key": "ussd.reset_guarded_pin",
"name": "reset_guarded_pin", "name": "reset_guarded_pin",
"parent": "pin_management" "parent": "pin_management"
}, },
"56": { "56": {
"description": "Pin entry for initiating request to reset an account's pin.", "description": "Pin entry for initiating request to reset an account's pin.",
"display_key": "ussd.kenya.reset_guarded_pin_authorization", "display_key": "ussd.reset_guarded_pin_authorization",
"name": "reset_guarded_pin_authorization", "name": "reset_guarded_pin_authorization",
"parent": "pin_management" "parent": "pin_management"
}, },
"57": { "57": {
"description": "Exit menu following successful pin reset initiation.", "description": "Exit menu following successful pin reset initiation.",
"display_key": "ussd.kenya.exit_pin_reset_initiated_success", "display_key": "ussd.exit_pin_reset_initiated_success",
"name": "exit_pin_reset_initiated_success", "name": "exit_pin_reset_initiated_success",
"parent": "pin_management" "parent": "pin_management"
}, },
"58": { "58": {
"description": "Exit menu in the event that an account is not a set guardian.", "description": "Exit menu in the event that an account is not a set guardian.",
"display_key": "ussd.kenya.exit_not_authorized_for_pin_reset", "display_key": "ussd.exit_not_authorized_for_pin_reset",
"name": "exit_not_authorized_for_pin_reset", "name": "exit_not_authorized_for_pin_reset",
"parent": "pin_management" "parent": "pin_management"
}, },
"59": { "59": {
"description": "Pin guard menu for handling guardianship operations.", "description": "Pin guard menu for handling guardianship operations.",
"display_key": "ussd.kenya.guard_pin", "display_key": "ussd.guard_pin",
"name": "guard_pin", "name": "guard_pin",
"parent": "pin_management" "parent": "pin_management"
}, },
"60": { "60": {
"description": "Pin entry to display a list of set guardians.", "description": "Pin entry to display a list of set guardians.",
"display_key": "ussd.kenya.guardian_list_pin_authorization", "display_key": "ussd.guardian_list_pin_authorization",
"name": "guardian_list_pin_authorization", "name": "guardian_list_pin_authorization",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"61": { "61": {
"description": "Menu to display list of set guardians.", "description": "Menu to display list of set guardians.",
"display_key": "ussd.kenya.guardian_list", "display_key": "ussd.guardian_list",
"name": "guardian_list", "name": "guardian_list",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"62": { "62": {
"description": "Phone number entry to add an account as a guardian to reset pin.", "description": "Phone number entry to add an account as a guardian to reset pin.",
"display_key": "ussd.kenya.add_guardian", "display_key": "ussd.add_guardian",
"name": "add_guardian", "name": "add_guardian",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"63": { "63": {
"description": "Pin entry to confirm addition of an account as a guardian.", "description": "Pin entry to confirm addition of an account as a guardian.",
"display_key": "ussd.kenya.add_guardian_pin_authorization", "display_key": "ussd.add_guardian_pin_authorization",
"name": "add_guardian_pin_authorization", "name": "add_guardian_pin_authorization",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"64": { "64": {
"description": "Exit menu when an account is successfully added as pin reset guardian.", "description": "Exit menu when an account is successfully added as pin reset guardian.",
"display_key": "ussd.kenya.exit_guardian_addition_success", "display_key": "ussd.exit_guardian_addition_success",
"name": "exit_guardian_addition_success", "name": "exit_guardian_addition_success",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"65": { "65": {
"description": "Phone number entry to remove an account as a guardian to reset pin.", "description": "Phone number entry to remove an account as a guardian to reset pin.",
"display_key": "ussd.kenya.remove_guardian", "display_key": "ussd.remove_guardian",
"name": "remove_guardian", "name": "remove_guardian",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"66": { "66": {
"description": "Pin entry to confirm removal of an account as a guardian.", "description": "Pin entry to confirm removal of an account as a guardian.",
"display_key": "ussd.kenya.remove_guardian_pin_authorization", "display_key": "ussd.remove_guardian_pin_authorization",
"name": "remove_guardian_pin_authorization", "name": "remove_guardian_pin_authorization",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"67": { "67": {
"description": "Exit menu when an account is successfully removed as pin reset guardian.", "description": "Exit menu when an account is successfully removed as pin reset guardian.",
"display_key": "ussd.kenya.exit_guardian_removal_success", "display_key": "ussd.exit_guardian_removal_success",
"name": "exit_guardian_removal_success", "name": "exit_guardian_removal_success",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"68": { "68": {
"description": "Exit menu when invalid phone number entry for guardian addition.", "description": "Exit menu when invalid phone number entry for guardian addition.",
"display_key": "ussd.kenya.exit_invalid_guardian_addition", "display_key": "ussd.exit_invalid_guardian_addition",
"name": "exit_invalid_guardian_addition", "name": "exit_invalid_guardian_addition",
"parent": "guard_pin" "parent": "guard_pin"
}, },
"69": { "69": {
"description": "Exit menu when invalid phone number entry for guardian removal.", "description": "Exit menu when invalid phone number entry for guardian removal.",
"display_key": "ussd.kenya.exit_invalid_guardian_removal", "display_key": "ussd.exit_invalid_guardian_removal",
"name": "exit_invalid_guardian_removal", "name": "exit_invalid_guardian_removal",
"parent": "guard_pin" "parent": "guard_pin"
},
"70": {
"description": "Menu to display middle set of languages to select.",
"display_key": "ussd.initial_middle_language_set",
"name": "initial_middle_language_set",
"parent": null
},
"71": {
"description": "Menu to display last set of languages to select.",
"display_key": "ussd.initial_last_language_set",
"name": "initial_last_language_set",
"parent": null
},
"72": {
"description": "Menu to display middle set of languages to select.",
"display_key": "ussd.middle_language_set",
"name": "middle_language_set",
"parent": null
},
"73": {
"description": "Menu to display last set of languages to select.",
"display_key": "ussd.last_language_set",
"name": "last_language_set",
"parent": null
} }
} }
} }

View File

@ -19,33 +19,32 @@ from cic_ussd.account.metadata import get_cached_preferred_language
from cic_ussd.account.statement import ( from cic_ussd.account.statement import (
get_cached_statement, get_cached_statement,
parse_statement_transactions, parse_statement_transactions,
query_statement, query_statement)
statement_transaction_set
)
from cic_ussd.account.tokens import (create_account_tokens_list, from cic_ussd.account.tokens import (create_account_tokens_list,
get_active_token_symbol, get_active_token_symbol,
get_cached_token_data, get_cached_token_data,
get_cached_token_symbol_list, get_cached_token_symbol_list,
get_cached_token_data_list, get_cached_token_data_list,
parse_token_list, parse_token_list)
token_list_set)
from cic_ussd.account.transaction import from_wei, to_wei from cic_ussd.account.transaction import from_wei, to_wei
from cic_ussd.cache import cache_data_key, cache_data from cic_ussd.cache import cache_data_key, cache_data, get_cached_data
from cic_ussd.db.models.account import Account from cic_ussd.db.models.account import Account
from cic_ussd.metadata import PersonMetadata from cic_ussd.metadata import PersonMetadata
from cic_ussd.phone_number import Support from cic_ussd.phone_number import Support
from cic_ussd.processor.util import parse_person_metadata from cic_ussd.processor.util import parse_person_metadata, ussd_menu_list, wait_for_session_data
from cic_ussd.session.ussd_session import save_session_data from cic_ussd.session.ussd_session import save_session_data
from cic_ussd.state_machine.logic.language import preferred_langauge_from_selection
from cic_ussd.translation import translation_for from cic_ussd.translation import translation_for
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
logg = logging.getLogger(__name__) logg = logging.getLogger(__file__)
class MenuProcessor: class MenuProcessor:
def __init__(self, account: Account, display_key: str, menu_name: str, session: Session, ussd_session: dict): def __init__(self, account: Account, display_key: str, menu_name: str, session: Session, ussd_session: dict):
self.account = account self.account = account
self.display_key = display_key self.display_key = display_key
if account:
self.identifier = bytes.fromhex(self.account.blockchain_address) self.identifier = bytes.fromhex(self.account.blockchain_address)
self.menu_name = menu_name self.menu_name = menu_name
self.session = session self.session = session
@ -89,36 +88,29 @@ class MenuProcessor:
:rtype: :rtype:
""" """
cached_statement = get_cached_statement(self.account.blockchain_address) cached_statement = get_cached_statement(self.account.blockchain_address)
transaction_sets = []
if cached_statement:
statement = json.loads(cached_statement)
statement_transactions = parse_statement_transactions(statement)
transaction_sets = [statement_transactions[tx:tx + 3] for tx in range(0, len(statement_transactions), 3)]
preferred_language = get_cached_preferred_language(self.account.blockchain_address) preferred_language = get_cached_preferred_language(self.account.blockchain_address)
if not preferred_language: if not preferred_language:
preferred_language = i18n.config.get('fallback') preferred_language = i18n.config.get('fallback')
no_transaction_history = statement_transaction_set(preferred_language, transaction_sets)
first_transaction_set = no_transaction_history
middle_transaction_set = no_transaction_history
last_transaction_set = no_transaction_history
if transaction_sets:
first_transaction_set = statement_transaction_set(preferred_language, transaction_sets[0])
if len(transaction_sets) >= 2:
middle_transaction_set = statement_transaction_set(preferred_language, transaction_sets[1])
if len(transaction_sets) >= 3:
last_transaction_set = statement_transaction_set(preferred_language, transaction_sets[2])
if self.display_key == 'ussd.kenya.first_transaction_set': statement_list = []
if cached_statement:
statement_list = parse_statement_transactions(statement=json.loads(cached_statement))
fallback = translation_for('helpers.no_transaction_history', preferred_language)
transaction_sets = ussd_menu_list(fallback=fallback, menu_list=statement_list, split=3)
if self.display_key == 'ussd.first_transaction_set':
return translation_for( return translation_for(
self.display_key, preferred_language, first_transaction_set=first_transaction_set self.display_key, preferred_language, first_transaction_set=transaction_sets[0]
) )
if self.display_key == 'ussd.kenya.middle_transaction_set': if self.display_key == 'ussd.middle_transaction_set':
return translation_for( return translation_for(
self.display_key, preferred_language, middle_transaction_set=middle_transaction_set self.display_key, preferred_language, middle_transaction_set=transaction_sets[1]
) )
if self.display_key == 'ussd.kenya.last_transaction_set': if self.display_key == 'ussd.last_transaction_set':
return translation_for( return translation_for(
self.display_key, preferred_language, last_transaction_set=last_transaction_set self.display_key, preferred_language, last_transaction_set=transaction_sets[2]
) )
def add_guardian_pin_authorization(self): def add_guardian_pin_authorization(self):
@ -129,7 +121,7 @@ class MenuProcessor:
preferred_language = get_cached_preferred_language(self.account.blockchain_address) preferred_language = get_cached_preferred_language(self.account.blockchain_address)
if not preferred_language: if not preferred_language:
preferred_language = i18n.config.get('fallback') preferred_language = i18n.config.get('fallback')
set_guardians = self.account.get_guardians() set_guardians = self.account.get_guardians()[:3]
if set_guardians: if set_guardians:
guardians_list = '' guardians_list = ''
guardians_list_header = translation_for('helpers.guardians_list_header', preferred_language) guardians_list_header = translation_for('helpers.guardians_list_header', preferred_language)
@ -145,36 +137,30 @@ class MenuProcessor:
def account_tokens(self) -> str: def account_tokens(self) -> str:
cached_token_data_list = get_cached_token_data_list(self.account.blockchain_address) cached_token_data_list = get_cached_token_data_list(self.account.blockchain_address)
token_data_list = parse_token_list(cached_token_data_list) token_data_list = parse_token_list(cached_token_data_list)
token_list_sets = [token_data_list[tds:tds + 3] for tds in range(0, len(token_data_list), 3)]
preferred_language = get_cached_preferred_language(self.account.blockchain_address) preferred_language = get_cached_preferred_language(self.account.blockchain_address)
if not preferred_language: if not preferred_language:
preferred_language = i18n.config.get('fallback') preferred_language = i18n.config.get('fallback')
no_token_list = token_list_set(preferred_language, [])
first_account_tokens_set = no_token_list fallback = translation_for('helpers.no_tokens_list', preferred_language)
middle_account_tokens_set = no_token_list token_list_sets = ussd_menu_list(fallback=fallback, menu_list=token_data_list, split=3)
last_account_tokens_set = no_token_list
if token_list_sets:
data = { data = {
'account_tokens_list': cached_token_data_list 'account_tokens_list': cached_token_data_list
} }
save_session_data(data=data, queue='cic-ussd', session=self.session, ussd_session=self.ussd_session) save_session_data(data=data, queue='cic-ussd', session=self.session, ussd_session=self.ussd_session)
first_account_tokens_set = token_list_set(preferred_language, token_list_sets[0])
if len(token_list_sets) >= 2: if self.display_key == 'ussd.first_account_tokens_set':
middle_account_tokens_set = token_list_set(preferred_language, token_list_sets[1])
if len(token_list_sets) >= 3:
last_account_tokens_set = token_list_set(preferred_language, token_list_sets[2])
if self.display_key == 'ussd.kenya.first_account_tokens_set':
return translation_for( return translation_for(
self.display_key, preferred_language, first_account_tokens_set=first_account_tokens_set self.display_key, preferred_language, first_account_tokens_set=token_list_sets[0]
) )
if self.display_key == 'ussd.kenya.middle_account_tokens_set': if self.display_key == 'ussd.middle_account_tokens_set':
return translation_for( return translation_for(
self.display_key, preferred_language, middle_account_tokens_set=middle_account_tokens_set self.display_key, preferred_language, middle_account_tokens_set=token_list_sets[1]
) )
if self.display_key == 'ussd.kenya.last_account_tokens_set': if self.display_key == 'ussd.last_account_tokens_set':
return translation_for( return translation_for(
self.display_key, preferred_language, last_account_tokens_set=last_account_tokens_set self.display_key, preferred_language, last_account_tokens_set=token_list_sets[2]
) )
def help(self) -> str: def help(self) -> str:
@ -222,7 +208,7 @@ class MenuProcessor:
remaining_attempts = 3 remaining_attempts = 3
remaining_attempts -= self.account.failed_pin_attempts remaining_attempts -= self.account.failed_pin_attempts
retry_pin_entry = translation_for( retry_pin_entry = translation_for(
'ussd.kenya.retry_pin_entry', preferred_language, remaining_attempts=remaining_attempts 'ussd.retry_pin_entry', preferred_language, remaining_attempts=remaining_attempts
) )
return translation_for( return translation_for(
f'{self.display_key}.retry', preferred_language, retry_pin_entry=retry_pin_entry f'{self.display_key}.retry', preferred_language, retry_pin_entry=retry_pin_entry
@ -238,6 +224,38 @@ class MenuProcessor:
guardian = Account.get_by_phone_number(guardian_phone_number, self.session) guardian = Account.get_by_phone_number(guardian_phone_number, self.session)
return guardian.standard_metadata_id() return guardian.standard_metadata_id()
def language(self):
key = cache_data_key('system:languages'.encode('utf-8'), MetadataPointer.NONE)
cached_system_languages = get_cached_data(key)
language_list: list = json.loads(cached_system_languages)
if self.account:
preferred_language = get_cached_preferred_language(self.account.blockchain_address)
else:
preferred_language = i18n.config.get('fallback')
fallback = translation_for('helpers.no_language_list', preferred_language)
language_list_sets = ussd_menu_list(fallback=fallback, menu_list=language_list, split=3)
if self.display_key in ['ussd.initial_language_selection', 'ussd.select_preferred_language']:
return translation_for(
self.display_key, preferred_language, first_language_set=language_list_sets[0]
)
if 'middle_language_set' in self.display_key:
return translation_for(
self.display_key, preferred_language, middle_language_set=language_list_sets[1]
)
if 'last_language_set' in self.display_key:
return translation_for(
self.display_key, preferred_language, last_language_set=language_list_sets[2]
)
def account_creation_prompt(self):
preferred_language = preferred_langauge_from_selection(self.ussd_session.get('user_input'))
return translation_for(self.display_key, preferred_language)
def reset_guarded_pin_authorization(self): def reset_guarded_pin_authorization(self):
guarded_account_information = self.guarded_account_metadata() guarded_account_information = self.guarded_account_metadata()
return self.pin_authorization(guarded_account_information=guarded_account_information) return self.pin_authorization(guarded_account_information=guarded_account_information)
@ -381,8 +399,9 @@ class MenuProcessor:
) )
def exit_invalid_menu_option(self): def exit_invalid_menu_option(self):
if self.account:
preferred_language = get_cached_preferred_language(self.account.blockchain_address) preferred_language = get_cached_preferred_language(self.account.blockchain_address)
if not preferred_language: else:
preferred_language = i18n.config.get('fallback') preferred_language = i18n.config.get('fallback')
return translation_for(self.display_key, preferred_language, support_phone=Support.phone_number) return translation_for(self.display_key, preferred_language, support_phone=Support.phone_number)
@ -390,7 +409,7 @@ class MenuProcessor:
preferred_language = get_cached_preferred_language(self.account.blockchain_address) preferred_language = get_cached_preferred_language(self.account.blockchain_address)
if not preferred_language: if not preferred_language:
preferred_language = i18n.config.get('fallback') preferred_language = i18n.config.get('fallback')
return translation_for('ussd.kenya.exit_pin_blocked', preferred_language, support_phone=Support.phone_number) return translation_for('ussd.exit_pin_blocked', preferred_language, support_phone=Support.phone_number)
def exit_successful_token_selection(self) -> str: def exit_successful_token_selection(self) -> str:
selected_token = self.ussd_session.get('data').get('selected_token') selected_token = self.ussd_session.get('data').get('selected_token')
@ -445,6 +464,9 @@ def response(account: Account, display_key: str, menu_name: str, session: Sessio
""" """
menu_processor = MenuProcessor(account, display_key, menu_name, session, ussd_session) menu_processor = MenuProcessor(account, display_key, menu_name, session, ussd_session)
if menu_name == 'account_creation_prompt':
return menu_processor.account_creation_prompt()
if menu_name == 'start': if menu_name == 'start':
return menu_processor.start_menu() return menu_processor.start_menu()
@ -502,6 +524,9 @@ def response(account: Account, display_key: str, menu_name: str, session: Sessio
if 'account_tokens_set' in menu_name: if 'account_tokens_set' in menu_name:
return menu_processor.account_tokens() return menu_processor.account_tokens()
if 'language' in menu_name:
return menu_processor.language()
if menu_name == 'display_user_metadata': if menu_name == 'display_user_metadata':
return menu_processor.person_metadata() return menu_processor.person_metadata()
@ -515,5 +540,4 @@ def response(account: Account, display_key: str, menu_name: str, session: Sessio
return menu_processor.exit_successful_token_selection() return menu_processor.exit_successful_token_selection()
preferred_language = get_cached_preferred_language(account.blockchain_address) preferred_language = get_cached_preferred_language(account.blockchain_address)
return translation_for(display_key, preferred_language) return translation_for(display_key, preferred_language)

View File

@ -8,7 +8,7 @@ from sqlalchemy.orm.session import Session
from tinydb.table import Document from tinydb.table import Document
# local imports # local imports
from cic_ussd.db.models.account import Account, create from cic_ussd.db.models.account import Account
from cic_ussd.db.models.base import SessionBase from cic_ussd.db.models.base import SessionBase
from cic_ussd.db.models.ussd_session import UssdSession from cic_ussd.db.models.ussd_session import UssdSession
from cic_ussd.menu.ussd_menu import UssdMenu from cic_ussd.menu.ussd_menu import UssdMenu
@ -16,7 +16,6 @@ from cic_ussd.processor.menu import response
from cic_ussd.processor.util import latest_input, resume_last_ussd_session from cic_ussd.processor.util import latest_input, resume_last_ussd_session
from cic_ussd.session.ussd_session import create_or_update_session, persist_ussd_session from cic_ussd.session.ussd_session import create_or_update_session, persist_ussd_session
from cic_ussd.state_machine import UssdStateMachine from cic_ussd.state_machine import UssdStateMachine
from cic_ussd.translation import translation_for
from cic_ussd.validator import is_valid_response from cic_ussd.validator import is_valid_response
@ -36,9 +35,6 @@ def handle_menu(account: Account, session: Session) -> Document:
last_ussd_session = UssdSession.last_ussd_session(account.phone_number, session) last_ussd_session = UssdSession.last_ussd_session(account.phone_number, session)
if last_ussd_session: if last_ussd_session:
return resume_last_ussd_session(last_ussd_session.state) return resume_last_ussd_session(last_ussd_session.state)
elif not account.has_preferred_language():
return UssdMenu.find_by_name('initial_language_selection')
else: else:
return UssdMenu.find_by_name('initial_pin_entry') return UssdMenu.find_by_name('initial_pin_entry')
@ -71,16 +67,13 @@ def get_menu(account: Account,
return UssdMenu.find_by_name(state) return UssdMenu.find_by_name(state)
def handle_menu_operations(chain_str: str, def handle_menu_operations(external_session_id: str,
external_session_id: str,
phone_number: str, phone_number: str,
queue: str, queue: str,
service_code: str, service_code: str,
session, session,
user_input: str): user_input: str):
""" """
:param chain_str:
:type chain_str:
:param external_session_id: :param external_session_id:
:type external_session_id: :type external_session_id:
:param phone_number: :param phone_number:
@ -100,10 +93,38 @@ def handle_menu_operations(chain_str: str,
account: Account = Account.get_by_phone_number(phone_number, session) account: Account = Account.get_by_phone_number(phone_number, session)
if account: if account:
return handle_account_menu_operations(account, external_session_id, queue, session, service_code, user_input) return handle_account_menu_operations(account, external_session_id, queue, session, service_code, user_input)
create(chain_str, phone_number, session) else:
menu = UssdMenu.find_by_name('account_creation_prompt') return handle_no_account_menu_operations(
preferred_language = i18n.config.get('fallback') account, external_session_id, phone_number, queue, session, service_code, user_input)
create_or_update_session(
def handle_no_account_menu_operations(account: Optional[Account],
external_session_id: str,
phone_number: str,
queue: str,
session: Session,
service_code: str,
user_input: str):
"""
:param account:
:type account:
:param external_session_id:
:type external_session_id:
:param phone_number:
:type phone_number:
:param queue:
:type queue:
:param session:
:type session:
:param service_code:
:type service_code:
:param user_input:
:type user_input:
:return:
:rtype:
"""
menu = UssdMenu.find_by_name('initial_language_selection')
ussd_session = create_or_update_session(
external_session_id=external_session_id, external_session_id=external_session_id,
msisdn=phone_number, msisdn=phone_number,
service_code=service_code, service_code=service_code,
@ -111,7 +132,20 @@ def handle_menu_operations(chain_str: str,
session=session, session=session,
user_input=user_input) user_input=user_input)
persist_ussd_session(external_session_id, queue) persist_ussd_session(external_session_id, queue)
return translation_for('ussd.kenya.account_creation_prompt', preferred_language) last_ussd_session: UssdSession = UssdSession.last_ussd_session(phone_number, session)
if last_ussd_session:
if not user_input:
menu = resume_last_ussd_session(last_ussd_session.state)
else:
session = SessionBase.bind_session(session)
state = next_state(account, session, user_input, last_ussd_session.to_json())
menu = UssdMenu.find_by_name(state)
return response(account=account,
display_key=menu.get('display_key'),
menu_name=menu.get('name'),
session=session,
ussd_session=ussd_session.to_json())
def handle_account_menu_operations(account: Account, def handle_account_menu_operations(account: Account,
@ -152,15 +186,12 @@ def handle_account_menu_operations(account: Account,
if last_ussd_session: if last_ussd_session:
ussd_session = create_or_update_session( ussd_session = create_or_update_session(
external_session_id, phone_number, service_code, user_input, menu.get('name'), session, external_session_id, phone_number, service_code, user_input, menu.get('name'), session,
last_ussd_session.data last_ussd_session.data)
)
else: else:
ussd_session = create_or_update_session( ussd_session = create_or_update_session(
external_session_id, phone_number, service_code, user_input, menu.get('name'), session, None external_session_id, phone_number, service_code, user_input, menu.get('name'), session, {})
)
menu_response = response( menu_response = response(
account, menu.get('display_key'), menu.get('name'), session, ussd_session.to_json() account, menu.get('display_key'), menu.get('name'), session, ussd_session.to_json())
)
if not is_valid_response(menu_response): if not is_valid_response(menu_response):
raise ValueError(f'Invalid response: {response}') raise ValueError(f'Invalid response: {response}')
persist_ussd_session(external_session_id, queue) persist_ussd_session(external_session_id, queue)

View File

@ -3,7 +3,7 @@ import datetime
import json import json
import logging import logging
import time import time
from typing import Union from typing import List, Union
# external imports # external imports
from cic_types.condiments import MetadataPointer from cic_types.condiments import MetadataPointer
@ -21,9 +21,7 @@ logg = logging.getLogger(__file__)
def latest_input(user_input: str) -> str: def latest_input(user_input: str) -> str:
""" """
:param user_input: :param user_input:
:type user_input:
:return: :return:
:rtype:
""" """
return user_input.split('*')[-1] return user_input.split('*')[-1]
@ -85,6 +83,27 @@ def resume_last_ussd_session(last_state: str) -> Document:
return UssdMenu.find_by_name(last_state) return UssdMenu.find_by_name(last_state)
def ussd_menu_list(fallback: str, menu_list: list, split: int = 3) -> List[str]:
"""
:param fallback:
:type fallback:
:param menu_list:
:type menu_list:
:param split:
:type split:
:return:
:rtype:
"""
menu_list_sets = [menu_list[item:item + split] for item in range(0, len(menu_list), split)]
menu_list_reprs = []
for i in range(split):
try:
menu_list_reprs.append(''.join(f'{list_set_item}\n' for list_set_item in menu_list_sets[i]).rstrip('\n'))
except IndexError:
menu_list_reprs.append(fallback)
return menu_list_reprs
def wait_for_cache(identifier: Union[list, bytes], resource_name: str, salt: MetadataPointer, interval: int = 1, max_retry: int = 5): def wait_for_cache(identifier: Union[list, bytes], resource_name: str, salt: MetadataPointer, interval: int = 1, max_retry: int = 5):
""" """
:param identifier: :param identifier:
@ -132,17 +151,28 @@ def wait_for_session_data(resource_name: str, session_data_key: str, ussd_sessio
:return: :return:
:rtype: :rtype:
""" """
session_data = ussd_session.get('data').get(session_data_key) data = ussd_session.get('data')
counter = 0 data_poller = 0
while session_data is None: while not data:
logg.debug(f'Waiting for: {resource_name}. Checking after: {interval} ...') logg.debug(f'Waiting for data object on ussd session: {ussd_session.get("external_session_id")}')
logg.debug(f'Data poller at: {data_poller}. Checking again after: {interval} secs...')
time.sleep(interval) time.sleep(interval)
counter += 1 data_poller += 1
session_data = ussd_session.get('data').get(session_data_key) if data:
if session_data is not None: logg.debug(f'Data object found, proceeding to poll for: {session_data_key}')
break
if data:
session_data_poller = 0
session_data = data.get(session_data_key)
while not session_data_key:
logg.debug(
f'Session data poller at: {data_poller} with max retry at: {max_retry}. Checking again after: {interval} secs...')
time.sleep(interval)
session_data_poller += 1
if session_data:
logg.debug(f'{resource_name} now available.') logg.debug(f'{resource_name} now available.')
break break
else:
if counter == max_retry: elif session_data_poller >= max_retry:
logg.debug(f'Could not find: {resource_name} within: {max_retry}') logg.debug(f'Could not find data object within: {max_retry}')
break

View File

@ -20,6 +20,7 @@ from cic_ussd.db import dsn_from_config
from cic_ussd.db.models.base import SessionBase from cic_ussd.db.models.base import SessionBase
from cic_ussd.phone_number import Support from cic_ussd.phone_number import Support
from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession
from cic_ussd.translation import generate_locale_files
from cic_ussd.validator import validate_presence from cic_ussd.validator import validate_presence
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
@ -83,6 +84,10 @@ if key_file_path:
validate_presence(path=key_file_path) validate_presence(path=key_file_path)
Signer.key_file_path = key_file_path Signer.key_file_path = key_file_path
generate_locale_files(locale_dir=config.get('LOCALE_PATH'),
schema_file_path=config.get('SCHEMA_FILE_PATH'),
translation_builder_path=config.get('LOCALE_FILE_BUILDERS'))
# set up translations # set up translations
i18n.load_path.append(config.get('LOCALE_PATH')) i18n.load_path.append(config.get('LOCALE_PATH'))
i18n.set('fallback', config.get('LOCALE_FALLBACK')) i18n.set('fallback', config.get('LOCALE_FALLBACK'))

View File

@ -18,6 +18,7 @@ from cic_types.ext.metadata.signer import Signer
# local imports # local imports
from cic_ussd.account.chain import Chain from cic_ussd.account.chain import Chain
from cic_ussd.account.guardianship import Guardianship
from cic_ussd.account.tokens import query_default_token from cic_ussd.account.tokens import query_default_token
from cic_ussd.cache import cache_data, cache_data_key, Cache from cic_ussd.cache import cache_data, cache_data_key, Cache
from cic_ussd.db import dsn_from_config from cic_ussd.db import dsn_from_config
@ -33,7 +34,7 @@ from cic_ussd.processor.ussd import handle_menu_operations
from cic_ussd.runnable.server_base import exportable_parser, logg from cic_ussd.runnable.server_base import exportable_parser, logg
from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession
from cic_ussd.state_machine import UssdStateMachine from cic_ussd.state_machine import UssdStateMachine
from cic_ussd.translation import translation_for from cic_ussd.translation import generate_locale_files, Languages, translation_for
from cic_ussd.validator import check_ip, check_request_content_length, validate_phone_number, validate_presence from cic_ussd.validator import check_ip, check_request_content_length, validate_phone_number, validate_presence
args = exportable_parser.parse_args() args = exportable_parser.parse_args()
@ -56,10 +57,6 @@ SessionBase.connect(data_source_name,
pool_size=int(config.get('DATABASE_POOL_SIZE')), pool_size=int(config.get('DATABASE_POOL_SIZE')),
debug=config.true('DATABASE_DEBUG')) debug=config.true('DATABASE_DEBUG'))
# set up translations
i18n.load_path.append(config.get('LOCALE_PATH'))
i18n.set('fallback', config.get('LOCALE_FALLBACK'))
# set Fernet key # set Fernet key
PasswordEncoder.set_key(config.get('APP_PASSWORD_PEPPER')) PasswordEncoder.set_key(config.get('APP_PASSWORD_PEPPER'))
@ -121,6 +118,22 @@ valid_service_codes = config.get('USSD_SERVICE_CODE').split(",")
E164Format.region = config.get('E164_REGION') E164Format.region = config.get('E164_REGION')
Support.phone_number = config.get('OFFICE_SUPPORT_PHONE') Support.phone_number = config.get('OFFICE_SUPPORT_PHONE')
validate_presence(config.get('SYSTEM_GUARDIANS_FILE'))
Guardianship.load_system_guardians(config.get('SYSTEM_GUARDIANS_FILE'))
generate_locale_files(locale_dir=config.get('LOCALE_PATH'),
schema_file_path=config.get('SCHEMA_FILE_PATH'),
translation_builder_path=config.get('LOCALE_FILE_BUILDERS'))
# set up translations
i18n.load_path.append(config.get('LOCALE_PATH'))
i18n.set('fallback', config.get('LOCALE_FALLBACK'))
validate_presence(config.get('LANGUAGES_FILE'))
Languages.load_languages_dict(config.get('LANGUAGES_FILE'))
languages = Languages()
languages.cache_system_languages()
def application(env, start_response): def application(env, start_response):
"""Loads python code for application to be accessible over web server """Loads python code for application to be accessible over web server
@ -175,7 +188,7 @@ def application(env, start_response):
if service_code not in valid_service_codes: if service_code not in valid_service_codes:
response = translation_for( response = translation_for(
'ussd.kenya.invalid_service_code', 'ussd.invalid_service_code',
i18n.config.get('fallback'), i18n.config.get('fallback'),
valid_service_code=valid_service_codes[0] valid_service_code=valid_service_codes[0]
) )
@ -189,9 +202,7 @@ def application(env, start_response):
return [] return []
logg.debug('session {} started for {}'.format(external_session_id, phone_number)) logg.debug('session {} started for {}'.format(external_session_id, phone_number))
response = handle_menu_operations( response = handle_menu_operations(external_session_id, phone_number, args.q, service_code, session, user_input)
chain_str, external_session_id, phone_number, args.q, service_code, session, user_input
)
response_bytes, headers = with_content_headers(headers, response) response_bytes, headers = with_content_headers(headers, response)
start_response('200 OK,', headers) start_response('200 OK,', headers)
session.commit() session.commit()

View File

@ -11,46 +11,20 @@ from cic_types.models.person import get_contact_data_from_vcard, generate_vcard_
# local imports # local imports
from cic_ussd.account.chain import Chain from cic_ussd.account.chain import Chain
from cic_ussd.account.maps import gender, language from cic_ussd.account.maps import gender
from cic_ussd.account.metadata import get_cached_preferred_language from cic_ussd.account.metadata import get_cached_preferred_language
from cic_ussd.db.models.account import Account from cic_ussd.db.models.account import Account, create
from cic_ussd.db.models.base import SessionBase from cic_ussd.db.models.base import SessionBase
from cic_ussd.error import MetadataNotFoundError from cic_ussd.error import MetadataNotFoundError
from cic_ussd.metadata import PersonMetadata from cic_ussd.metadata import PersonMetadata
from cic_ussd.session.ussd_session import save_session_data from cic_ussd.session.ussd_session import save_session_data
from cic_ussd.state_machine.logic.language import preferred_langauge_from_selection
from cic_ussd.translation import translation_for from cic_ussd.translation import translation_for
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
logg = logging.getLogger(__file__) logg = logging.getLogger(__file__)
def change_preferred_language(state_machine_data: Tuple[str, dict, Account, Session]):
"""
:param state_machine_data:
:type state_machine_data:
:return:
:rtype:
"""
user_input, ussd_session, account, session = state_machine_data
r_user_input = language().get(user_input)
session = SessionBase.bind_session(session)
account.preferred_language = r_user_input
session.add(account)
session.flush()
SessionBase.release_session(session)
preferences_data = {
'preferred_language': r_user_input
}
s = celery.signature(
'cic_ussd.tasks.metadata.add_preferences_metadata',
[account.blockchain_address, preferences_data],
queue='cic-ussd'
)
return s.apply_async()
def update_account_status_to_active(state_machine_data: Tuple[str, dict, Account, Session]): def update_account_status_to_active(state_machine_data: Tuple[str, dict, Account, Session]):
"""This function sets user's account to active. """This function sets user's account to active.
:param state_machine_data: A tuple containing user input, a ussd session and user object. :param state_machine_data: A tuple containing user input, a ussd session and user object.
@ -245,3 +219,16 @@ def edit_user_metadata_attribute(state_machine_data: Tuple[str, dict, Account, S
[blockchain_address, parsed_person_metadata] [blockchain_address, parsed_person_metadata]
) )
s_edit_person_metadata.apply_async(queue='cic-ussd') s_edit_person_metadata.apply_async(queue='cic-ussd')
def process_account_creation(state_machine_data: Tuple[str, dict, Account, Session]):
"""
:param state_machine_data:
:type state_machine_data:
:return:
:rtype:
"""
user_input, ussd_session, account, session = state_machine_data
preferred_language = preferred_langauge_from_selection(user_input=user_input)
chain_str = Chain.spec.__str__()
create(chain_str, ussd_session.get('msisdn'), session, preferred_language)

View File

@ -0,0 +1,95 @@
# standard imports
import json
from typing import Tuple
# external imports
import celery
import i18n
from cic_types.condiments import MetadataPointer
from sqlalchemy.orm.session import Session
# local imports
from cic_ussd.cache import cache_data_key, get_cached_data
from cic_ussd.db.models.account import Account
from cic_ussd.processor.util import wait_for_cache, wait_for_session_data
from cic_ussd.session.ussd_session import save_session_data
from cic_ussd.translation import Languages
def is_valid_language_selection(state_machine_data: Tuple[str, dict, Account, Session]):
"""
:param state_machine_data:
:type state_machine_data:
:return:
:rtype:
"""
user_input, ussd_session, account, session = state_machine_data
key = cache_data_key('system:languages'.encode('utf-8'), MetadataPointer.NONE)
cached_system_languages = get_cached_data(key)
language_list = json.loads(cached_system_languages)
if not language_list:
wait_for_cache(identifier='system:languages'.encode('utf-8'), resource_name='Languages list', salt=MetadataPointer.NONE)
if user_input in ['00', '11', '22']:
return False
user_input = int(user_input)
return user_input <= len(language_list)
def change_preferred_language(state_machine_data: Tuple[str, dict, Account, Session]):
"""
:param state_machine_data:
:type state_machine_data:
:return:
:rtype:
"""
process_language_selection(state_machine_data=state_machine_data)
user_input, ussd_session, account, session = state_machine_data
wait_for_session_data(resource_name='Preferred language', session_data_key='preferred_language', ussd_session=ussd_session)
preferred_language = ussd_session.get('data').get('preferred_language')
preferences_data = {
'preferred_language': preferred_language
}
s = celery.signature(
'cic_ussd.tasks.metadata.add_preferences_metadata',
[account.blockchain_address, preferences_data],
queue='cic-ussd'
)
return s.apply_async()
def process_language_selection(state_machine_data: Tuple[str, dict, Account, Session]):
"""
:param state_machine_data:
:type state_machine_data:
:return:
:rtype:
"""
user_input, ussd_session, account, session = state_machine_data
preferred_language = preferred_langauge_from_selection(user_input=user_input)
data = {
'preferred_language': preferred_language
}
save_session_data(queue='cic-ussd', session=session, data=data, ussd_session=ussd_session)
def preferred_langauge_from_selection(user_input: str):
"""
:param user_input:
:type user_input:
:return:
:rtype:
"""
key = cache_data_key('system:languages'.encode('utf-8'), MetadataPointer.NONE)
cached_system_languages = get_cached_data(key)
language_list = json.loads(cached_system_languages)
user_input = int(user_input)
selected_language = language_list[user_input - 1]
preferred_language = i18n.config.get('fallback')
for key, value in Languages.languages_dict.items():
if selected_language[3:] == value:
preferred_language = key
return preferred_language

View File

@ -9,9 +9,11 @@ from phonenumbers.phonenumberutil import NumberParseException
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
# local imports # local imports
from cic_ussd.account.guardianship import Guardianship
from cic_ussd.account.metadata import get_cached_preferred_language from cic_ussd.account.metadata import get_cached_preferred_language
from cic_ussd.db.models.account import Account from cic_ussd.db.models.account import Account
from cic_ussd.db.models.base import SessionBase from cic_ussd.db.models.base import SessionBase
from cic_ussd.notifications import Notifier
from cic_ussd.phone_number import process_phone_number, E164Format from cic_ussd.phone_number import process_phone_number, E164Format
from cic_ussd.session.ussd_session import save_session_data from cic_ussd.session.ussd_session import save_session_data
from cic_ussd.translation import translation_for from cic_ussd.translation import translation_for
@ -82,6 +84,8 @@ def is_valid_guardian_addition(state_machine_data: Tuple[str, dict, Account, Ses
preferred_language = i18n.config.get('fallback') preferred_language = i18n.config.get('fallback')
is_valid_account = Account.get_by_phone_number(phone_number, session) is not None is_valid_account = Account.get_by_phone_number(phone_number, session) is not None
guardianship = Guardianship()
is_system_guardian = guardianship.is_system_guardian(phone_number)
is_initiator = phone_number == account.phone_number is_initiator = phone_number == account.phone_number
is_existent_guardian = phone_number in account.get_guardians() is_existent_guardian = phone_number in account.get_guardians()
@ -100,7 +104,7 @@ def is_valid_guardian_addition(state_machine_data: Tuple[str, dict, Account, Ses
session_data['failure_reason'] = failure_reason session_data['failure_reason'] = failure_reason
save_session_data('cic-ussd', session, session_data, ussd_session) save_session_data('cic-ussd', session, session_data, ussd_session)
return phone_number is not None and is_valid_account and not is_existent_guardian and not is_initiator return phone_number is not None and is_valid_account and not is_existent_guardian and not is_initiator and not is_system_guardian
def add_pin_guardian(state_machine_data: Tuple[str, dict, Account, Session]): def add_pin_guardian(state_machine_data: Tuple[str, dict, Account, Session]):
@ -130,6 +134,9 @@ def is_set_pin_guardian(account: Account, checked_number: str, preferred_languag
is_set_guardian = checked_number in set_guardians is_set_guardian = checked_number in set_guardians
is_initiator = checked_number == account.phone_number is_initiator = checked_number == account.phone_number
guardianship = Guardianship()
is_system_guardian = guardianship.is_system_guardian(checked_number)
if not is_set_guardian: if not is_set_guardian:
failure_reason = translation_for('helpers.error.is_not_existent_guardian', preferred_language) failure_reason = translation_for('helpers.error.is_not_existent_guardian', preferred_language)
@ -141,7 +148,7 @@ def is_set_pin_guardian(account: Account, checked_number: str, preferred_languag
session_data['failure_reason'] = failure_reason session_data['failure_reason'] = failure_reason
save_session_data('cic-ussd', session, session_data, ussd_session) save_session_data('cic-ussd', session, session_data, ussd_session)
return is_set_guardian and not is_initiator return (is_set_guardian or is_system_guardian) and not is_initiator
def is_dialers_pin_guardian(state_machine_data: Tuple[str, dict, Account, Session]): def is_dialers_pin_guardian(state_machine_data: Tuple[str, dict, Account, Session]):
@ -193,8 +200,20 @@ def initiate_pin_reset(state_machine_data: Tuple[str, dict, Account, Session]):
save_session_data('cic-ussd', session, session_data, ussd_session) save_session_data('cic-ussd', session, session_data, ussd_session)
guarded_account_phone_number = session_data.get('guarded_account_phone_number') guarded_account_phone_number = session_data.get('guarded_account_phone_number')
guarded_account = Account.get_by_phone_number(guarded_account_phone_number, session) guarded_account = Account.get_by_phone_number(guarded_account_phone_number, session)
if quorum_count >= guarded_account.guardian_quora: if quorum_count >= guarded_account.guardian_quora:
guarded_account.reset_pin(session) guarded_account.reset_pin(session)
logg.debug(f'Reset initiated for: {guarded_account.phone_number}') logg.debug(f'Reset initiated for: {guarded_account.phone_number}')
session_data['quorum_count'] = 0 session_data['quorum_count'] = 0
save_session_data('cic-ussd', session, session_data, ussd_session) save_session_data('cic-ussd', session, session_data, ussd_session)
preferred_language = get_cached_preferred_language(guarded_account.blockchain_address)
if not preferred_language:
preferred_language = i18n.config.get('fallback')
notifier = Notifier()
notifier.send_sms_notification(
key='sms.pin_reset_initiated',
phone_number=guarded_account.phone_number,
preferred_language=preferred_language,
pin_initiator=account.standard_metadata_id())

View File

@ -23,7 +23,7 @@ def is_valid_token_selection(state_machine_data: Tuple[str, dict, Account, Sessi
account_tokens_list = session_data.get('account_tokens_list') account_tokens_list = session_data.get('account_tokens_list')
if not account_tokens_list: if not account_tokens_list:
wait_for_session_data('Account token list', session_data_key='account_tokens_list', ussd_session=ussd_session) wait_for_session_data('Account token list', session_data_key='account_tokens_list', ussd_session=ussd_session)
if user_input not in ['00', '22']: if user_input not in ['00', '11', '22']:
try: try:
user_input = int(user_input) user_input = int(user_input)
return user_input <= len(account_tokens_list) return user_input <= len(account_tokens_list)

View File

@ -32,14 +32,14 @@ celery_app = celery.current_app
@celery_app.task(bind=True, base=CriticalSQLAlchemyTask) @celery_app.task(bind=True, base=CriticalSQLAlchemyTask)
def account_creation_callback(self, result: str, url: str, status_code: int): def account_creation_callback(self, result: str, param: str, status_code: int):
"""This function defines a task that creates a user and """This function defines a task that creates a user and
:param self: Reference providing access to the callback task instance. :param self: Reference providing access to the callback task instance.
:type self: celery.Task :type self: celery.Task
:param result: The blockchain address for the created account :param result: The blockchain address for the created account
:type result: str :type result: str
:param url: URL provided to callback task in cic-eth should http be used for callback. :param param: URL provided to callback task in cic-eth should http be used for callback.
:type url: str :type param: str
:param status_code: The status of the task to create an account :param status_code: The status of the task to create an account
:type status_code: int :type status_code: int
""" """
@ -69,6 +69,15 @@ def account_creation_callback(self, result: str, url: str, status_code: int):
set_active_token(blockchain_address=result, token_symbol=token_symbol) set_active_token(blockchain_address=result, token_symbol=token_symbol)
queue = self.request.delivery_info.get('routing_key') queue = self.request.delivery_info.get('routing_key')
preferences_data = {"preferred_language": param}
# temporarily caching selected language
key = cache_data_key(bytes.fromhex(result), MetadataPointer.PREFERENCES)
cache_data(key, json.dumps(preferences_data))
s_preferences_metadata = celery.signature(
'cic_ussd.tasks.metadata.add_preferences_metadata', [result, preferences_data], queue=queue
)
s_preferences_metadata.apply_async()
s_phone_pointer = celery.signature( s_phone_pointer = celery.signature(
'cic_ussd.tasks.metadata.add_phone_pointer', [result, phone_number], queue=queue 'cic_ussd.tasks.metadata.add_phone_pointer', [result, phone_number], queue=queue
) )

View File

@ -1,9 +1,56 @@
""" """
This module is responsible for translation of ussd menu text based on a user's set preferred language. This module is responsible for translation of ussd menu text based on a user's set preferred language.
""" """
# standard imports
import json
import i18n import i18n
import os
from pathlib import Path
from typing import Optional from typing import Optional
# external imports
from cic_translations.processor import generate_translation_files, parse_csv
from cic_types.condiments import MetadataPointer
# local imports
from cic_ussd.cache import cache_data, cache_data_key
from cic_ussd.validator import validate_presence
def generate_locale_files(locale_dir: str, schema_file_path: str, translation_builder_path: str):
""""""
translation_builder_files = os.listdir(translation_builder_path)
for file in translation_builder_files:
props = Path(file)
if props.suffix == '.csv':
parsed_csv = parse_csv(os.path.join(translation_builder_path, file))
generate_translation_files(
parsed_csv=parsed_csv,
schema_file_path=schema_file_path,
translation_file_type=props.stem,
translation_file_path=locale_dir
)
class Languages:
languages_dict: dict = None
@classmethod
def load_languages_dict(cls, languages_file: str):
with open(languages_file, "r") as languages_file:
cls.languages_dict = json.load(languages_file)
def cache_system_languages(self):
system_languages: list = list(self.languages_dict.values())
languages_list = []
for i in range(len(system_languages)):
language = f'{i + 1}. {system_languages[i]}'
languages_list.append(language)
key = cache_data_key('system:languages'.encode('utf-8'), MetadataPointer.NONE)
cache_data(key, json.dumps(languages_list))
def translation_for(key: str, preferred_language: Optional[str] = None, **kwargs) -> str: def translation_for(key: str, preferred_language: Optional[str] = None, **kwargs) -> str:
""" """

View File

@ -11,3 +11,6 @@ transitions=transitions/
host = host =
port = port =
ssl = ssl =
[system]
guardians_file = var/lib/sys/guardians.txt

View File

@ -1,3 +1,10 @@
[locale] [locale]
fallback=sw fallback=sw
path=var/lib/locale/ path=var/lib/locale/
file_builders=var/lib/sys/
[schema]
file_path = /usr/local/lib/python3.8/site-packages/cic_translations/data/schema
[languages]
file = var/lib/sys/languages.json

View File

@ -4,8 +4,9 @@ billiard==3.6.4.0
bcrypt==3.2.0 bcrypt==3.2.0
celery==4.4.7 celery==4.4.7
cffi==1.14.6 cffi==1.14.6
cic-eth~=0.12.6 cic-eth~=0.12.7
cic-notify~=0.4.0a12 cic-notify~=0.4.0a12
cic-translations~=0.0.3
cic-types~=0.2.1a8 cic-types~=0.2.1a8
confini~=0.5.2 confini~=0.5.2
cic-eth-aux-erc20-demurrage-token~=0.0.3 cic-eth-aux-erc20-demurrage-token~=0.0.3

View File

@ -13,5 +13,7 @@
"products_edit_pin_authorization", "products_edit_pin_authorization",
"account_balances_pin_authorization", "account_balances_pin_authorization",
"account_statement_pin_authorization", "account_statement_pin_authorization",
"account_balances" "account_balances",
"middle_language_set",
"last_language_set"
] ]

View File

@ -2,6 +2,8 @@
"start", "start",
"scan_data", "scan_data",
"initial_language_selection", "initial_language_selection",
"initial_middle_language_set",
"initial_last_language_set",
"initial_pin_entry", "initial_pin_entry",
"initial_pin_confirmation", "initial_pin_confirmation",
"change_preferred_language" "change_preferred_language"

View File

@ -47,11 +47,11 @@ def test_menu_processor(activated_account,
preferred_language = get_cached_preferred_language(activated_account.blockchain_address) preferred_language = get_cached_preferred_language(activated_account.blockchain_address)
available_balance = get_cached_available_balance(activated_account.blockchain_address) available_balance = get_cached_available_balance(activated_account.blockchain_address)
token_symbol = get_default_token_symbol() token_symbol = get_default_token_symbol()
with_available_balance = 'ussd.kenya.account_balances.available_balance' with_available_balance = 'ussd.account_balances.available_balance'
with_fees = 'ussd.kenya.account_balances.with_fees' with_fees = 'ussd.account_balances.with_fees'
ussd_menu = UssdMenu.find_by_name('account_balances') ussd_menu = UssdMenu.find_by_name('account_balances')
name = ussd_menu.get('name') name = ussd_menu.get('name')
resp = response(activated_account, 'ussd.kenya.account_balances', name, init_database, generic_ussd_session) resp = response(activated_account, 'ussd.account_balances', name, init_database, generic_ussd_session)
assert resp == translation_for(with_available_balance, assert resp == translation_for(with_available_balance,
preferred_language, preferred_language,
available_balance=available_balance, available_balance=available_balance,
@ -61,7 +61,7 @@ def test_menu_processor(activated_account,
key = cache_data_key(identifier, MetadataPointer.BALANCES_ADJUSTED) key = cache_data_key(identifier, MetadataPointer.BALANCES_ADJUSTED)
adjusted_balance = 45931650.64654012 adjusted_balance = 45931650.64654012
cache_data(key, json.dumps(adjusted_balance)) cache_data(key, json.dumps(adjusted_balance))
resp = response(activated_account, 'ussd.kenya.account_balances', name, init_database, generic_ussd_session) resp = response(activated_account, 'ussd.account_balances', name, init_database, generic_ussd_session)
tax_wei = to_wei(int(available_balance)) - int(adjusted_balance) tax_wei = to_wei(int(available_balance)) - int(adjusted_balance)
tax = from_wei(int(tax_wei)) tax = from_wei(int(tax_wei))
assert resp == translation_for(key=with_fees, assert resp == translation_for(key=with_fees,
@ -84,28 +84,28 @@ def test_menu_processor(activated_account,
if len(transaction_sets) >= 3: if len(transaction_sets) >= 3:
last_transaction_set = statement_transaction_set(preferred_language, transaction_sets[2]) last_transaction_set = statement_transaction_set(preferred_language, transaction_sets[2])
display_key = 'ussd.kenya.first_transaction_set' display_key = 'ussd.first_transaction_set'
ussd_menu = UssdMenu.find_by_name('first_transaction_set') ussd_menu = UssdMenu.find_by_name('first_transaction_set')
name = ussd_menu.get('name') name = ussd_menu.get('name')
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
assert resp == translation_for(display_key, preferred_language, first_transaction_set=first_transaction_set) assert resp == translation_for(display_key, preferred_language, first_transaction_set=first_transaction_set)
display_key = 'ussd.kenya.middle_transaction_set' display_key = 'ussd.middle_transaction_set'
ussd_menu = UssdMenu.find_by_name('middle_transaction_set') ussd_menu = UssdMenu.find_by_name('middle_transaction_set')
name = ussd_menu.get('name') name = ussd_menu.get('name')
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
assert resp == translation_for(display_key, preferred_language, middle_transaction_set=middle_transaction_set) assert resp == translation_for(display_key, preferred_language, middle_transaction_set=middle_transaction_set)
display_key = 'ussd.kenya.last_transaction_set' display_key = 'ussd.last_transaction_set'
ussd_menu = UssdMenu.find_by_name('last_transaction_set') ussd_menu = UssdMenu.find_by_name('last_transaction_set')
name = ussd_menu.get('name') name = ussd_menu.get('name')
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
assert resp == translation_for(display_key, preferred_language, last_transaction_set=last_transaction_set) assert resp == translation_for(display_key, preferred_language, last_transaction_set=last_transaction_set)
display_key = 'ussd.kenya.display_user_metadata' display_key = 'ussd.display_user_metadata'
ussd_menu = UssdMenu.find_by_name('display_user_metadata') ussd_menu = UssdMenu.find_by_name('display_user_metadata')
name = ussd_menu.get('name') name = ussd_menu.get('name')
identifier = bytes.fromhex(activated_account.blockchain_address) identifier = bytes.fromhex(activated_account.blockchain_address)
@ -114,7 +114,7 @@ def test_menu_processor(activated_account,
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
assert resp == parse_person_metadata(cached_person_metadata, display_key, preferred_language) assert resp == parse_person_metadata(cached_person_metadata, display_key, preferred_language)
display_key = 'ussd.kenya.account_balances_pin_authorization' display_key = 'ussd.account_balances_pin_authorization'
ussd_menu = UssdMenu.find_by_name('account_balances_pin_authorization') ussd_menu = UssdMenu.find_by_name('account_balances_pin_authorization')
name = ussd_menu.get('name') name = ussd_menu.get('name')
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
@ -122,11 +122,11 @@ def test_menu_processor(activated_account,
activated_account.failed_pin_attempts = 1 activated_account.failed_pin_attempts = 1
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
retry_pin_entry = translation_for('ussd.kenya.retry_pin_entry', preferred_language, remaining_attempts=2) retry_pin_entry = translation_for('ussd.retry_pin_entry', preferred_language, remaining_attempts=2)
assert resp == translation_for(f'{display_key}.retry', preferred_language, retry_pin_entry=retry_pin_entry) assert resp == translation_for(f'{display_key}.retry', preferred_language, retry_pin_entry=retry_pin_entry)
activated_account.failed_pin_attempts = 0 activated_account.failed_pin_attempts = 0
display_key = 'ussd.kenya.start' display_key = 'ussd.start'
ussd_menu = UssdMenu.find_by_name('start') ussd_menu = UssdMenu.find_by_name('start')
name = ussd_menu.get('name') name = ussd_menu.get('name')
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
@ -135,7 +135,7 @@ def test_menu_processor(activated_account,
account_balance=available_balance, account_balance=available_balance,
account_token_name=token_symbol) account_token_name=token_symbol)
display_key = 'ussd.kenya.start' display_key = 'ussd.start'
ussd_menu = UssdMenu.find_by_name('start') ussd_menu = UssdMenu.find_by_name('start')
name = ussd_menu.get('name') name = ussd_menu.get('name')
older_timestamp = (activated_account.created - datetime.timedelta(days=35)) older_timestamp = (activated_account.created - datetime.timedelta(days=35))
@ -144,7 +144,7 @@ def test_menu_processor(activated_account,
response(activated_account, display_key, name, init_database, generic_ussd_session) response(activated_account, display_key, name, init_database, generic_ussd_session)
assert mock_get_adjusted_balance['timestamp'] == int((datetime.datetime.now() - datetime.timedelta(days=30)).timestamp()) assert mock_get_adjusted_balance['timestamp'] == int((datetime.datetime.now() - datetime.timedelta(days=30)).timestamp())
display_key = 'ussd.kenya.transaction_pin_authorization' display_key = 'ussd.transaction_pin_authorization'
ussd_menu = UssdMenu.find_by_name('transaction_pin_authorization') ussd_menu = UssdMenu.find_by_name('transaction_pin_authorization')
name = ussd_menu.get('name') name = ussd_menu.get('name')
generic_ussd_session['data'] = { generic_ussd_session['data'] = {
@ -163,7 +163,7 @@ def test_menu_processor(activated_account,
token_symbol=token_symbol, token_symbol=token_symbol,
sender_information=tx_sender_information) sender_information=tx_sender_information)
display_key = 'ussd.kenya.exit_insufficient_balance' display_key = 'ussd.exit_insufficient_balance'
ussd_menu = UssdMenu.find_by_name('exit_insufficient_balance') ussd_menu = UssdMenu.find_by_name('exit_insufficient_balance')
name = ussd_menu.get('name') name = ussd_menu.get('name')
generic_ussd_session['data'] = { generic_ussd_session['data'] = {
@ -180,13 +180,13 @@ def test_menu_processor(activated_account,
recipient_information=tx_recipient_information, recipient_information=tx_recipient_information,
token_balance=available_balance) token_balance=available_balance)
display_key = 'ussd.kenya.exit_invalid_menu_option' display_key = 'ussd.exit_invalid_menu_option'
ussd_menu = UssdMenu.find_by_name('exit_invalid_menu_option') ussd_menu = UssdMenu.find_by_name('exit_invalid_menu_option')
name = ussd_menu.get('name') name = ussd_menu.get('name')
resp = response(activated_account, display_key, name, init_database, generic_ussd_session) resp = response(activated_account, display_key, name, init_database, generic_ussd_session)
assert resp == translation_for(display_key, preferred_language, support_phone=Support.phone_number) assert resp == translation_for(display_key, preferred_language, support_phone=Support.phone_number)
display_key = 'ussd.kenya.exit_successful_transaction' display_key = 'ussd.exit_successful_transaction'
ussd_menu = UssdMenu.find_by_name('exit_successful_transaction') ussd_menu = UssdMenu.find_by_name('exit_successful_transaction')
name = ussd_menu.get('name') name = ussd_menu.get('name')
generic_ussd_session['data'] = { generic_ussd_session['data'] = {

View File

@ -97,7 +97,7 @@ def test_handle_menu_operations(activated_account,
valid_service_codes = load_config.get('USSD_SERVICE_CODE').split(",") valid_service_codes = load_config.get('USSD_SERVICE_CODE').split(",")
preferred_language = i18n.config.get('fallback') preferred_language = i18n.config.get('fallback')
resp = handle_menu_operations(chain_str, external_session_id, phone, None, valid_service_codes[0], init_database, '4444') resp = handle_menu_operations(chain_str, external_session_id, phone, None, valid_service_codes[0], init_database, '4444')
assert resp == translation_for('ussd.kenya.account_creation_prompt', preferred_language) assert resp == translation_for('ussd.account_creation_prompt', preferred_language)
cached_ussd_session = get_cached_data(external_session_id) cached_ussd_session = get_cached_data(external_session_id)
ussd_session = json.loads(cached_ussd_session) ussd_session = json.loads(cached_ussd_session)
assert ussd_session['msisdn'] == phone assert ussd_session['msisdn'] == phone
@ -118,5 +118,5 @@ def test_handle_menu_operations(activated_account,
preferred_language = get_cached_preferred_language(activated_account.blockchain_address) preferred_language = get_cached_preferred_language(activated_account.blockchain_address)
persisted_ussd_session.state = 'enter_transaction_recipient' persisted_ussd_session.state = 'enter_transaction_recipient'
resp = handle_menu_operations(chain_str, external_session_id, phone, None, valid_service_codes[0], init_database, '1') resp = handle_menu_operations(chain_str, external_session_id, phone, None, valid_service_codes[0], init_database, '1')
assert resp == translation_for('ussd.kenya.enter_transaction_recipient', preferred_language) assert resp == translation_for('ussd.enter_transaction_recipient', preferred_language)

View File

@ -32,7 +32,7 @@ def test_parse_person_metadata(activated_account, cache_person_metadata, cache_p
cached_person_metadata = person_metadata.get_cached_metadata() cached_person_metadata = person_metadata.get_cached_metadata()
person_metadata = json.loads(cached_person_metadata) person_metadata = json.loads(cached_person_metadata)
preferred_language = get_cached_preferred_language(activated_account.blockchain_address) preferred_language = get_cached_preferred_language(activated_account.blockchain_address)
display_key = 'ussd.kenya.display_person_metadata' display_key = 'ussd.display_person_metadata'
parsed_person_metadata = parse_person_metadata(cached_person_metadata, parsed_person_metadata = parse_person_metadata(cached_person_metadata,
display_key, display_key,
preferred_language) preferred_language)

View File

@ -8,8 +8,8 @@ from cic_ussd.notifications import Notifier
@pytest.mark.parametrize("key, preferred_language, recipient, expected_message", [ @pytest.mark.parametrize("key, preferred_language, recipient, expected_message", [
("ussd.kenya.exit", "en", "+254712345678", "END Thank you for using the service."), ("ussd.exit", "en", "+254712345678", "END Thank you for using the service."),
("ussd.kenya.exit", "sw", "+254712345678", "END Asante kwa kutumia huduma.") ("ussd.exit", "sw", "+254712345678", "END Asante kwa kutumia huduma.")
]) ])
def test_send_sms_notification(celery_session_worker, def test_send_sms_notification(celery_session_worker,
expected_message, expected_message,

View File

@ -10,11 +10,11 @@ from cic_ussd.translation import translation_for
def test_translation_for(set_locale_files): def test_translation_for(set_locale_files):
english_translation = translation_for( english_translation = translation_for(
key='ussd.kenya.exit_invalid_request', key='ussd.exit_invalid_request',
preferred_language='en' preferred_language='en'
) )
swahili_translation = translation_for( swahili_translation = translation_for(
key='ussd.kenya.exit_invalid_request', key='ussd.exit_invalid_request',
preferred_language='sw' preferred_language='sw'
) )
assert swahili_translation == 'END Chaguo si sahihi.' assert swahili_translation == 'END Chaguo si sahihi.'

View File

@ -1,21 +1,142 @@
[ [
{ {
"trigger": "scan_data", "trigger": "scan_data",
"source": "select_preferred_language", "source": "initial_language_selection",
"dest": "account_creation_prompt",
"after": "cic_ussd.state_machine.logic.account.process_account_creation",
"conditions": "cic_ussd.state_machine.logic.language.is_valid_language_selection"
},
{
"trigger": "scan_data",
"source": "initial_language_selection",
"dest": "initial_middle_language_set",
"conditions": "cic_ussd.state_machine.logic.menu.menu_eleven_selected"
},
{
"trigger": "scan_data",
"source": "initial_language_selection",
"dest": "exit", "dest": "exit",
"after": "cic_ussd.state_machine.logic.account.change_preferred_language", "conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
"conditions": "cic_ussd.state_machine.logic.menu.menu_one_selected" },
{
"trigger": "scan_data",
"source": "initial_middle_language_set",
"dest": "initial_language_selection",
"conditions": "cic_ussd.state_machine.logic.menu.menu_twenty_two_selected"
},
{
"trigger": "scan_data",
"source": "initial_middle_language_set",
"dest": "initial_last_language_set",
"conditions": "cic_ussd.state_machine.logic.menu.menu_eleven_selected"
},
{
"trigger": "scan_data",
"source": "initial_middle_language_set",
"dest": "exit",
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
},
{
"trigger": "scan_data",
"source": "initial_last_language_set",
"dest": "initial_middle_language_set",
"conditions": "cic_ussd.state_machine.logic.menu.menu_twenty_two_selected"
},
{
"trigger": "scan_data",
"source": "initial_last_language_set",
"dest": "exit",
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
},
{
"trigger": "scan_data",
"source": "initial_middle_language_set",
"dest": "exit",
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
},
{
"trigger": "scan_data",
"source": "initial_language_selection",
"dest": "exit_invalid_menu_option"
},
{
"trigger": "scan_data",
"source": "middle_language_set",
"dest": "exit_invalid_menu_option"
},
{
"trigger": "scan_data",
"source": "last_language_set",
"dest": "exit_invalid_menu_option"
}, },
{ {
"trigger": "scan_data", "trigger": "scan_data",
"source": "select_preferred_language", "source": "select_preferred_language",
"dest": "exit", "dest": "exit",
"after": "cic_ussd.state_machine.logic.account.change_preferred_language", "after": "cic_ussd.state_machine.logic.language.change_preferred_language",
"conditions": "cic_ussd.state_machine.logic.menu.menu_two_selected" "conditions": "cic_ussd.state_machine.logic.language.is_valid_language_selection"
},
{
"trigger": "scan_data",
"source": "select_preferred_language",
"dest": "middle_language_set",
"conditions": "cic_ussd.state_machine.logic.menu.menu_eleven_selected"
},
{
"trigger": "scan_data",
"source": "select_preferred_language",
"dest": "exit",
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
},
{
"trigger": "scan_data",
"source": "middle_language_set",
"dest": "select_preferred_language",
"conditions": "cic_ussd.state_machine.logic.menu.menu_twenty_two_selected"
},
{
"trigger": "scan_data",
"source": "middle_language_set",
"dest": "last_language_set",
"conditions": "cic_ussd.state_machine.logic.menu.menu_eleven_selected"
},
{
"trigger": "scan_data",
"source": "middle_language_set",
"dest": "exit",
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
},
{
"trigger": "scan_data",
"source": "last_language_set",
"dest": "middle_language_set",
"conditions": "cic_ussd.state_machine.logic.menu.menu_twenty_two_selected"
},
{
"trigger": "scan_data",
"source": "last_language_set",
"dest": "exit",
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
},
{
"trigger": "scan_data",
"source": "middle_language_set",
"dest": "exit",
"conditions": "cic_ussd.state_machine.logic.menu.menu_zero_zero_selected"
}, },
{ {
"trigger": "scan_data", "trigger": "scan_data",
"source": "select_preferred_language", "source": "select_preferred_language",
"dest": "exit_invalid_menu_option" "dest": "exit_invalid_menu_option"
},
{
"trigger": "scan_data",
"source": "middle_language_set",
"dest": "exit_invalid_menu_option"
},
{
"trigger": "scan_data",
"source": "last_language_set",
"dest": "exit_invalid_menu_option"
} }
] ]

View File

@ -1,29 +1,4 @@
[ [
{
"trigger": "scan_data",
"source": "initial_language_selection",
"dest": "initial_pin_entry",
"after": "cic_ussd.state_machine.logic.account.change_preferred_language",
"conditions": "cic_ussd.state_machine.logic.menu.menu_one_selected"
},
{
"trigger": "scan_data",
"source": "initial_language_selection",
"dest": "initial_pin_entry",
"after": "cic_ussd.state_machine.logic.account.change_preferred_language",
"conditions": "cic_ussd.state_machine.logic.menu.menu_two_selected"
},
{
"trigger": "scan_data",
"source": "initial_language_selection",
"dest": "help",
"conditions": "cic_ussd.state_machine.logic.menu.menu_three_selected"
},
{
"trigger": "scan_data",
"source": "initial_language_selection",
"dest": "exit_invalid_menu_option"
},
{ {
"trigger": "scan_data", "trigger": "scan_data",
"source": "initial_pin_entry", "source": "initial_pin_entry",
@ -39,7 +14,6 @@
{ {
"trigger": "scan_data", "trigger": "scan_data",
"source": "initial_pin_confirmation", "source": "initial_pin_confirmation",
"unless": "cic_ussd.state_machine.logic.validator.has_cached_person_metadata",
"conditions": "cic_ussd.state_machine.logic.pin.pins_match", "conditions": "cic_ussd.state_machine.logic.pin.pins_match",
"dest": "start", "dest": "start",
"after": [ "after": [

View File

@ -1,36 +0,0 @@
en:
female: |-
Female
from: |-
From
male: |-
Male
not_provided: |-
Not provided
no_transaction_history: |-
No transaction history
no_tokens_list: |-
No tokens to list
other: |-
Other
received: |-
Received
sent: |-
Sent
to: |-
To
guardians_list_header: |-
Walinzi uliowaongeza ni:
no_guardians_list: |-
No guardians set
error:
no_phone_number_provided: |-
No phone number was provided.
no_matching_account: |-
The number provided is not registered.
is_initiator: |-
Phone number cannot be your own.
is_existent_guardian: |-
This phone number is is already added as a guardian.
is_not_existent_guardian: |-
Phone number not set as PIN reset guardian.

View File

@ -1,36 +0,0 @@
sw:
female: |-
Mwanamke
from: |-
Kutoka kwa
male: |-
Mwanaume
not_provided: |-
Haijawekwa
no_transaction_history: |-
Hamna ripoti ya matumizi
no_tokens_list: |-
Hamna sarafu nyingine
other: |-
Nyingine
received: |-
Ulipokea
sent: |-
Ulituma
to: |-
Kwa
guardians_list_header: |-
Your set guardians are:
no_guardians_list: |-
Hamna walinzi walioongezwa
error:
no_phone_number_provided: |-
Namabari ya simu haijawekwa.
no_matching_account: |-
Nambari uliyoweka haijasajiliwa.
is_initiator: |-
Nambari yafaa kuwa tofauti na yako.
is_existent_guardian: |-
Namabari hii tayari imeongezwa kama mlinzi wa nambari ya siri.
is_not_existent_guardian: |-
Nambari hii haijaongezwa kama mlinzi wa nambari ya siri.

View File

@ -1,11 +0,0 @@
en:
account_successfully_created: |-
You have been registered on Sarafu Network! To use dial *384*96# on Safaricom and *483*96# on other networks. For help %{support_phone}.
received_tokens: |-
Successfully received %{amount} %{token_symbol} from %{tx_sender_information} %{timestamp} to %{tx_recipient_information}. New balance is %{balance} %{token_symbol}.
sent_tokens: |-
Successfully sent %{amount} %{token_symbol} to %{tx_recipient_information} %{timestamp} from %{tx_sender_information}. New balance is %{balance} %{token_symbol}.
terms: |-
By using the service, you agree to the terms and conditions at http://grassecon.org/tos
upsell_unregistered_recipient: |-
%{tx_sender_information} tried to send you %{token_symbol} but you are not registered. To use dial *384*96# on Safaricom and *483*96# on other networks. For help %{support_phone}.

View File

@ -1,11 +0,0 @@
sw:
account_successfully_created: |-
Umesajiliwa kwa huduma ya Sarafu! Kutumia bonyeza *384*96# Safaricom ama *483*46# kwa utandao tofauti. Kwa Usaidizi %{support_phone}.
received_tokens: |-
Umepokea %{amount} %{token_symbol} kutoka kwa %{tx_sender_information} %{timestamp} ikapokewa na %{tx_recipient_information}. Salio lako ni %{balance} %{token_symbol}.
sent_tokens: |-
Umetuma %{amount} %{token_symbol} kwa %{tx_recipient_information} %{timestamp} kutoka kwa %{tx_sender_information}. Salio lako ni %{balance} %{token_symbol}.
terms: |-
Kwa kutumia hii huduma, umekubali sheria na masharti yafuatayo http://grassecon.org/tos
upsell_unregistered_recipient: |-
%{tx_sender_information} amejaribu kukutumia %{token_symbol} lakini hujasajili. Kutumia bonyeza *384*96# Safaricom ama *483*46# kwa utandao tofauti. Kwa Usaidizi %{support_phone}.

View File

@ -1,317 +0,0 @@
en:
kenya:
initial_language_selection: |-
CON Welcome to Sarafu Network
1. English
2. Kiswahili
3. Help
initial_pin_entry: |-
CON Please enter a new four number PIN for your account.
initial_pin_confirmation: |-
CON Enter your four number PIN again
enter_given_name: |-
CON Enter first name
0. Back
enter_family_name: |-
CON Enter family name
0. Back
enter_date_of_birth: |-
CON Enter year of birth
0. Back
enter_gender: |-
CON Enter gender
1. Male
2. Female
3. Other
0. Back
enter_location: |-
CON Enter your location
0. Back
enter_products: |-
CON Please enter a product or service you offer
0. Back
start: |-
CON Balance %{account_balance} %{account_token_name}
1. Send
2. My Sarafu
3. My Account
4. Help
enter_transaction_recipient: |-
CON Enter phone number
0. Back
enter_transaction_amount: |-
CON Enter amount
0. Back
first_account_tokens_set: |-
CON Choose a number or symbol from your balances:
%{first_account_tokens_set}
11. Next
00. Exit
middle_account_tokens_set: |-
CON Choose a number or symbol from your balances:
%{middle_account_tokens_set}
11. Next
22. Previous
00. Exit
last_account_tokens_set: |-
CON Choose a number or symbol from your balances:
%{last_account_tokens_set}
22. Previous
00. Exit
token_selection_pin_authorization:
first: |-
CON %{token_data}
Enter pin to select:
retry: |-
%{retry_pin_entry}
account_management: |-
CON My account
1. My profile
2. Change language
3. Check balance
4. Check statement
5. PIN options
0. Back
metadata_management: |-
CON My profile
1. Edit name
2. Edit gender
3. Edit age
4. Edit location
5. Edit products
6. View my profile
0. Back
display_user_metadata: |-
CON Your details are:
Name: %{full_name}
Gender: %{gender}
Age: %{age}
Location: %{location}
You sell: %{products}
0. Back
select_preferred_language: |-
CON Choose language
1. English
2. Kiswahili
0. Back
retry_pin_entry: |-
CON Incorrect PIN entered, please try again. You have %{remaining_attempts} attempts remaining.
0. Back
pin_management: |-
CON Pin options
1. Change PIN
2. Reset PIN
3. Guard PIN
0. Back
enter_current_pin:
first: |-
CON Enter current PIN.
0. Back
retry: |-
%{retry_pin_entry}
enter_new_pin: |-
CON Enter your new four number PIN
0. Back
new_pin_confirmation: |-
CON Enter your new four number PIN again
0. Back
reset_guarded_pin: |-
CON Enter phone number you are the guardian to reset their pin
0. Back
reset_guarded_pin_authorization:
first: |-
CON Enter YOUR pin to confirm %{guarded_account_information}'s reset
0. Back
retry: |-
%{retry_pin_entry}
exit_pin_reset_initiated_success: |-
CON Success: You have initiated a PIN reset for %{guarded_account_information}
0. Back
9. Exit
exit_not_authorized_for_pin_reset: |-
CON Failure: You are not authorized to reset that PIN. You must be a guardian!
0. Back
9. Exit
guard_pin: |-
CON Pin guard
1. View guardians
2. Add guardian
3. Remove guardian
0. Back
guardian_list_pin_authorization:
first: |-
CON Enter your pin to view set guardians
0. Back
retry: |-
%{retry_pin_entry}
guardian_list: |-
CON %{guardians_list}
0. Back
9. Exit
add_guardian: |-
CON Enter phone number to add as pin reset guardian
0. Back
add_guardian_pin_authorization:
first: |-
CON Enter your pin to add %{guardian_information} as your PIN reset guardian
0. Back
retry: |-
%{retry_pin_entry}
exit_guardian_addition_success: |-
CON Success: %{guardian_information} can now reset your PIN
0. Back
9. Exit
exit_invalid_guardian_addition: |-
CON %{error_exit}
0. Back
9. Exit
remove_guardian: |-
CON Enter phone number to revoke guardianship:
0. Back
remove_guardian_pin_authorization:
first: |-
CON Enter your pin to remove %{guardian_information} as your PIN reset guardian
0. Back
retry: |-
%{retry_pin_entry}
exit_guardian_removal_success: |-
CON Success: %{guardian_information} PIN reset guardianship is revoked
0. Back
9. Exit
exit_invalid_guardian_removal: |-
CON %{error_exit}
0. Back
9. Exit
transaction_pin_authorization:
first: |-
CON %{recipient_information} will receive %{transaction_amount} %{token_symbol} from %{sender_information}.
Please enter your PIN to confirm.
0. Back
retry: |-
%{retry_pin_entry}
display_metadata_pin_authorization:
first: |-
CON Please enter your PIN
0. Back
retry: |-
%{retry_pin_entry}
account_balances_pin_authorization:
first: |-
CON Please enter your PIN to view balances
0. Back
retry: |-
%{retry_pin_entry}
account_statement_pin_authorization:
first: |-
CON Please enter your PIN to view statement
0. Back
retry: |-
%{retry_pin_entry}
name_edit_pin_authorization:
first: |-
CON Please enter your PIN
0. Back
retry: |-
%{retry_pin_entry}
dob_edit_pin_authorization:
first: |-
CON Please enter your PIN
0. Back
retry: |-
%{retry_pin_entry}
gender_edit_pin_authorization:
first: |-
CON Please enter your PIN
0. Back
retry: |-
%{retry_pin_entry}
location_edit_pin_authorization:
first: |-
CON Please enter your PIN
0. Back
retry: |-
%{retry_pin_entry}
products_edit_pin_authorization:
first: |-
CON Please enter your PIN
0. Back
retry: |-
%{retry_pin_entry}
account_balances:
available_balance: |-
CON Your balances are as follows:
balance: %{available_balance} %{token_symbol}
0. Back
with_fees: |-
CON Your balances are as follows:
balances: %{available_balance} %{token_symbol}
fees: %{tax} %{token_symbol}
0. Back
with_rewards: |-
CON Your balances are as follows:
balance: %{available_balance} %{token_symbol}
fees: %{tax} %{token_symbol}
rewards: %{bonus} %{token_symbol}
0. Back
first_transaction_set: |-
CON %{first_transaction_set}
1. Next
00. Exit
middle_transaction_set: |-
CON %{middle_transaction_set}
1. Next
2. Previous
00. Exit
last_transaction_set: |-
CON %{last_transaction_set}
2. Previous
00. Exit
exit: |-
END Thank you for using the service.
exit_invalid_request: |-
END Invalid request.
exit_invalid_menu_option: |-
CON Invalid menu option. For help, call %{support_phone}.
00. Back
99. Exit
exit_invalid_input: |-
CON Invalid input. Nothing selected
00. Back
99. Exit
exit_pin_blocked: |-
END Your PIN has been blocked. For help, please call %{support_phone}.
exit_invalid_pin: |-
END The PIN you have entered is invalid. PIN must consist of 4 digits. For help, call %{support_phone}.
exit_invalid_new_pin: |-
END The PIN you have entered is invalid. PIN must be different from your current PIN. For help, call %{support_phone}.
exit_pin_mismatch: |-
END The new PIN does not match the one you entered. Please try again. For help, call %{support_phone}.
exit_invalid_recipient: |-
CON Recipient's phone number is not registered or is invalid:
00. Retry
99. Exit
exit_successful_transaction: |-
CON Your request has been sent. %{recipient_information} will receive %{transaction_amount} %{token_symbol} from %{sender_information}.
00. Back
99. Exit
exit_insufficient_balance: |-
CON Payment of %{amount} %{token_symbol} to %{recipient_information} has failed due to insufficent balance.
Your Sarafu-Network balances is: %{token_balance}
00. Back
99. Exit
exit_successful_token_selection: |-
CON Success! %{token_symbol} is your active Sarafu.
00. Back
99. Exit
invalid_service_code: |-
Please dial %{valid_service_code} to access Sarafu Network
help: |-
CON For assistance call %{support_phone}
00. Back
99. Exit
complete: |-
CON Your request has been sent. You will receive an SMS shortly.
00. Back
99. Exit
account_creation_prompt: |-
END Your account is being created. You will receive an SMS when your account is ready.

View File

@ -1,316 +0,0 @@
sw:
kenya:
initial_language_selection: |-
CON Karibu Sarafu Network
1. English
2. Kiswahili
3. Help
initial_pin_entry: |-
CON Tafadhali weka pin mpya yenye nambari nne kwa akaunti yako
initial_pin_confirmation: |-
CON Weka PIN yako tena
enter_given_name: |-
CON Weka jina lako la kwanza
enter_family_name: |-
CON Weka jina lako la mwisho
0. Nyuma
enter_date_of_birth: |-
CON Weka mwaka wa kuzaliwa
0. Nyuma
enter_gender: |-
CON Weka jinsia yako
1. Mwanaume
2. Mwanamke
3. Nyngine
0. Nyuma
enter_location: |-
CON Weka eneo lako
0. Nyuma
enter_products: |-
CON Weka bidhaa ama huduma unauza
0. Nyuma
start: |-
CON Salio %{account_balance} %{account_token_name}
1. Tuma
2. Sarafu yangu
3. Akaunti yangu
4. Usaidizi
enter_transaction_recipient: |-
CON Weka nambari ya simu
0. Nyuma
enter_transaction_amount: |-
CON Weka kiwango
0. Nyuma
first_account_tokens_set: |-
CON Chagua nambari au ishara kutoka kwa salio zako:
%{first_account_tokens_set}
11. Mbele
00. Ondoka
middle_account_tokens_set: |-
CON Chagua nambari au ishara kutoka kwa salio zako:
%{middle_account_tokens_set}
11. Mbele
22. Nyuma
00. Ondoka
last_account_tokens_set: |-
CON Chagua nambari au ishara kutoka kwa salio zako:
%{last_account_tokens_set}
22. Nyuma
00. Ondoka
token_selection_pin_authorization:
first: |-
CON %{token_data}
Weka nambari ya siri kuchagua:
retry: |-
%{retry_pin_entry}
account_management: |-
CON Akaunti yangu
1. Wasifu wangu
2. Chagua lugha utakayotumia
3. Angalia salio
4. Angalia taarifa ya matumizi
5. Mipangilio ya nambari ya siri
0. Nyuma
metadata_management: |-
CON Wasifu wangu
1. Weka jina
2. Weka jinsia
3. Weka umri
4. Weka eneo
5. Weka bidhaa
6. Angalia wasifu wako
0. Nyuma
display_user_metadata: |-
CON Wasifu wako una maelezo yafuatayo:
Jina: %{full_name}
Jinsia: %{gender}
Umri: %{age}
Eneo: %{location}
Unauza: %{products}
0. Nyuma
select_preferred_language: |-
CON Chagua lugha
1. Kingereza
2. Kiswahili
0. Nyuma
retry_pin_entry: |-
CON Nambari uliyoweka si sahihi, jaribu tena. Una majaribio %{remaining_attempts} yaliyobaki.
0. Nyuma
pin_management: |-
CON Pin options
1. Badilisha nambari yangu ya siri
2. Tuma ombili la kubadilisha nambari ya siri
3. Linda nambari ya siri
0. Nyuma
enter_current_pin:
first: |-
CON Weka nambari ya siri.
0. Nyuma
retry: |-
%{retry_pin_entry}
enter_new_pin: |-
CON Weka nambari ya siri mpya
0. Nyuma
new_pin_confirmation: |-
CON Weka nambari yako ya siri tena
0. Nyuma
reset_guarded_pin: |-
CON Weka nambari ya simu ili kutuma ombi la kubalisha nambari ya siri.
0. Nyuma
reset_guarded_pin_authorization:
first: |-
CON Weka nambari YAKO ya siri ili kudhibitisha ombi la kubadilisha nambari ya siri ya %{guarded_account_information}.
0. Nyuma
retry: |-
%{retry_pin_entry}
exit_pin_reset_initiated_success: |-
CON Ombi lako la kubadili nambari ya siri ya %{guarded_account_information} limetumwa.
0. Nyuma
9. Ondoka
exit_not_authorized_for_pin_reset: |-
CON Huruhusiwi kutuma ombi la kubadilisha nambari ya siri.
0. Nyuma
9. Ondoka
guard_pin: |-
CON Linda nambari ya siri
1. Walinzi wa namabari ya siri
2. Ongeza mlinzi
3. Ondoa mlinzi
0. Nyuma
guardian_list_pin_authorization:
first: |-
CON Weka nambari yako ya siri ili kuona walinzi uliowaongeza
0. Nyuma
retry: |-
%{retry_pin_entry}
guardian_list: |-
CON %{guardians_list}
0. Nyuma
9. Ondoka
add_guardian: |-
CON Weka nambari ya simu ili kuongeza mlinzi
0. Nyuma
add_guardian_pin_authorization:
first: |-
CON Weka nambari YAKO ya siri ili kumwongeza %{guardian_information} kama mlinzi
0. Nyuma
retry: |-
%{retry_pin_entry}
exit_guardian_addition_success: |-
CON Ombi lako la kumwongeza: %{guardian_information} kama mlinzi limefanikiwa
0. Nyuma
9. Ondoka
exit_invalid_guardian_addition: |-
CON %{error_exit}
0. Nyuma
9. Ondoka
remove_guardian: |-
CON Weka nambari ya simu ili kuondoa mlinzi
0. Nyuma
remove_guardian_pin_authorization:
first: |-
CON Weka nambari YAKO ya siri ili kumwondoa %{guardian_information} kama mlinzi
0. Nyuma
retry: |-
%{retry_pin_entry}
exit_guardian_removal_success: |-
CON Ombi lako la kumwondoa: %{guardian_information} kama mlinzi limefanikiwa
0. Nyuma
9. Ondoka
exit_invalid_guardian_removal: |-
CON %{error_exit}
0. Nyuma
9. Ondoka
transaction_pin_authorization:
first: |-
CON %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}.
Tafadhali weka nambari yako ya siri kudhibitisha.
0. Nyuma
retry: |-
%{retry_pin_entry}
display_metadata_pin_authorization:
first: |-
CON Tafadhali weka PIN yako
0. Nyuma
retry: |-
%{retry_pin_entry}
account_balances_pin_authorization:
first: |-
CON Tafadhali weka PIN yako kuona salio.
0. Nyuma
retry: |-
%{retry_pin_entry}
account_statement_pin_authorization:
first: |-
CON Tafadhali weka PIN yako kuona taarifa ya matumizi.
0. Nyuma
retry: |-
%{retry_pin_entry}
name_edit_pin_authorization:
first: |-
CON Tafadhali weka PIN yako
0. Nyuma
retry: |-
%{retry_pin_entry}
dob_edit_pin_authorization:
first: |-
CON Tafadhali weka PIN yako
0. Nyuma
retry: |-
%{retry_pin_entry}
gender_edit_pin_authorization:
first: |-
CON Tafadhali weka PIN yako
0. Nyuma
retry: |-
%{retry_pin_entry}
location_edit_pin_authorization:
first: |-
CON Tafadhali weka PIN yako
0. Nyuma
retry: |-
%{retry_pin_entry}
products_edit_pin_authorization:
first: |-
CON Tafadhali weka PIN yako
0. Nyuma
retry: |-
%{retry_pin_entry}
account_balances:
available_balance: |-
CON Salio zako ni zifuatazo:
salio: %{available_balance} %{token_symbol}
0. Nyuma
with_fees: |-
CON Salio zako ni zifuatazo:
salio: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
0. Nyuma
with_rewards: |-
CON Salio zako ni zifuatazo:
salio: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
tuzo: %{bonus} %{token_symbol}
0. Nyuma
first_transaction_set: |-
CON %{first_transaction_set}
1. Mbele
00. Ondoka
middle_transaction_set: |-
CON %{middle_transaction_set}
1. Mbele
2. Nyuma
00. Ondoka
last_transaction_set: |-
CON %{last_transaction_set}
2. Nyuma
00. Ondoka
exit: |-
END Asante kwa kutumia huduma.
exit_invalid_request: |-
END Chaguo si sahihi.
exit_invalid_menu_option: |-
CON Chaguo lako sio sahihi. Kwa usaidizi piga simu %{support_phone}
00. Nyuma
99. Ondoka
exit_invalid_input: |-
CON Chaguo lako halipatikani. Hakuna kilichochaguliwa.
00. Nyuma
99. Ondoka
exit_pin_blocked: |-
END PIN yako imefungwa. Kwa usaidizi tafadhali piga simu %{support_phone}.
exit_invalid_pin: |-
END PIN uliyobonyeza sio sahihi. PIN lazima iwe na nambari nne. Kwa usaidizi piga simu %{support_phone}.
exit_invalid_new_pin: |-
END PIN uliyobonyeza sio sahihi. PIN lazima iwe tofauti na pin yako ya sasa. Kwa usaidizi piga simu %{support_phone}.
exit_pin_mismatch: |-
END PIN mpya na udhibitisho wa pin mpya hazilingani. Tafadhali jaribu tena. Kwa usaidizi piga simu %{support_phone}.
exit_invalid_recipient: |-
CON Mpokeaji wa nambari hapatikani au sio sahihi.
00. Jaribu tena
99. Ondoka
exit_successful_transaction: |-
CON Ombi lako limetumwa. %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}.
00. Nyuma
99. Ondoka
exit_insufficient_balance: |-
CON Malipo ya %{amount} %{token_symbol} kwa %{recipient_information} halijakamilika kwa sababu salio lako haitoshi.
Akaunti yako ya Sarafu ina salio ifuatayo: %{token_balance}
00. Nyuma
99. Ondoka
exit_successful_token_selection: |-
CON Chaguo lako limekamilika, %{token_symbol} ni sarafu itakayotumika.
00. Nyuma
99. Ondoka
invalid_service_code: |-
Bonyeza %{valid_service_code} kutumia mtandao wa Sarafu
help: |-
CON Kwa usaidizi piga simu %{support_phone}
0. Nyuma
9. Ondoka
complete: |-
CON Ombi lako limetumwa. Utapokea uthibitishaji wa SMS kwa muda mfupi.
00. Nyuma
99. Ondoka
account_creation_prompt: |-
END Akaunti yako ya Sarafu inatayarishwa. Utapokea ujumbe wa SMS akaunti yako ikiwa tayari.

View File

View File

@ -0,0 +1,19 @@
keys,en,sw
female,Female,Mwanamke
from,From,Kutoka kwa
male,Male,Mwanaume
not_provided,Not provided,Haijawekwa
no_language_list,No language list,Hamna lugha ya kuchagua
no_transaction_history,No transaction history,Hamna ripoti ya matumizi
no_tokens_list,No tokens to list,Hamna sarafu nyingine
other,Other,Nyingine
received,Received,Ulipokea
sent,Sent,Ulituma
to,To,Kwa
guardians_list_header,Your set guardians are:,Walinzi uliowaongeza ni:
no_guardians_list,No guardians set,Hamna walinzi walioongezwa
error.no_phone_number_provided,No phone number was provided.,Namabari ya simu haijawekwa.
error.no_matching_account,The number provided is not registered.,Nambari uliyoweka haijasajiliwa.
error.is_initiator,Phone number cannot be your own.,Nambari yafaa kuwa tofauti na yako.
error.is_existent_guardian,This phone number is is already added as a guardian.,Namabari hii tayari imeongezwa kama mlinzi wa nambari ya siri.
error.is_not_existent_guardian,Phone number not set as PIN reset guardian.,Nambari hii haijaongezwa kama mlinzi wa nambari ya siri.
1 keys en sw
2 female Female Mwanamke
3 from From Kutoka kwa
4 male Male Mwanaume
5 not_provided Not provided Haijawekwa
6 no_language_list No language list Hamna lugha ya kuchagua
7 no_transaction_history No transaction history Hamna ripoti ya matumizi
8 no_tokens_list No tokens to list Hamna sarafu nyingine
9 other Other Nyingine
10 received Received Ulipokea
11 sent Sent Ulituma
12 to To Kwa
13 guardians_list_header Your set guardians are: Walinzi uliowaongeza ni:
14 no_guardians_list No guardians set Hamna walinzi walioongezwa
15 error.no_phone_number_provided No phone number was provided. Namabari ya simu haijawekwa.
16 error.no_matching_account The number provided is not registered. Nambari uliyoweka haijasajiliwa.
17 error.is_initiator Phone number cannot be your own. Nambari yafaa kuwa tofauti na yako.
18 error.is_existent_guardian This phone number is is already added as a guardian. Namabari hii tayari imeongezwa kama mlinzi wa nambari ya siri.
19 error.is_not_existent_guardian Phone number not set as PIN reset guardian. Nambari hii haijaongezwa kama mlinzi wa nambari ya siri.

View File

@ -0,0 +1,9 @@
{
"en": "English",
"sw": "Kiswahili",
"kam": "Kamba",
"kik": "Kikiuyu",
"miji": "Mijikenda",
"luo": "Luo",
"bor": "Borana"
}

View File

@ -0,0 +1,7 @@
keys,en,sw
account_successfully_created,You have been registered on Sarafu Network! To use dial *384*96# on Safaricom and *483*96# on other networks. For help %{support_phone}.,Umesajiliwa kwa huduma ya Sarafu! Kutumia bonyeza *384*96# Safaricom ama *483*46# kwa utandao tofauti. Kwa Usaidizi %{support_phone}.
received_tokens,Successfully received %{amount} %{token_symbol} from %{tx_sender_information} %{timestamp} to %{tx_recipient_information}. New balance is %{balance} %{token_symbol}.,Umepokea %{amount} %{token_symbol} kutoka kwa %{tx_sender_information} %{timestamp} ikapokewa na %{tx_recipient_information}. Salio lako ni %{balance} %{token_symbol}.
sent_tokens,Successfully sent %{amount} %{token_symbol} to %{tx_recipient_information} %{timestamp} from %{tx_sender_information}. New balance is %{balance} %{token_symbol}.,Umetuma %{amount} %{token_symbol} kwa %{tx_recipient_information} %{timestamp} kutoka kwa %{tx_sender_information}. Salio lako ni %{balance} %{token_symbol}.
terms,"By using the service, you agree to the terms and conditions at http://grassecon.org/tos","Kwa kutumia hii huduma, umekubali sheria na masharti yafuatayo http://grassecon.org/tos"
upsell_unregistered_recipient,%{tx_sender_information} tried to send you %{token_symbol} but you are not registered. To use dial *384*96# on Safaricom and *483*96# on other networks. For help %{support_phone}.,%{tx_sender_information} amejaribu kukutumia %{token_symbol} lakini hujasajili. Kutumia bonyeza *384*96# Safaricom ama *483*46# kwa utandao tofauti. Kwa Usaidizi %{support_phone}.
pin_reset_initiated,%{pin_initiator} has sent a request to initiate your PIN reset.,%{pin_initiator} ametuma ombi la kubadilisha PIN yako.
1 keys en sw
2 account_successfully_created You have been registered on Sarafu Network! To use dial *384*96# on Safaricom and *483*96# on other networks. For help %{support_phone}. Umesajiliwa kwa huduma ya Sarafu! Kutumia bonyeza *384*96# Safaricom ama *483*46# kwa utandao tofauti. Kwa Usaidizi %{support_phone}.
3 received_tokens Successfully received %{amount} %{token_symbol} from %{tx_sender_information} %{timestamp} to %{tx_recipient_information}. New balance is %{balance} %{token_symbol}. Umepokea %{amount} %{token_symbol} kutoka kwa %{tx_sender_information} %{timestamp} ikapokewa na %{tx_recipient_information}. Salio lako ni %{balance} %{token_symbol}.
4 sent_tokens Successfully sent %{amount} %{token_symbol} to %{tx_recipient_information} %{timestamp} from %{tx_sender_information}. New balance is %{balance} %{token_symbol}. Umetuma %{amount} %{token_symbol} kwa %{tx_recipient_information} %{timestamp} kutoka kwa %{tx_sender_information}. Salio lako ni %{balance} %{token_symbol}.
5 terms By using the service, you agree to the terms and conditions at http://grassecon.org/tos Kwa kutumia hii huduma, umekubali sheria na masharti yafuatayo http://grassecon.org/tos
6 upsell_unregistered_recipient %{tx_sender_information} tried to send you %{token_symbol} but you are not registered. To use dial *384*96# on Safaricom and *483*96# on other networks. For help %{support_phone}. %{tx_sender_information} amejaribu kukutumia %{token_symbol} lakini hujasajili. Kutumia bonyeza *384*96# Safaricom ama *483*46# kwa utandao tofauti. Kwa Usaidizi %{support_phone}.
7 pin_reset_initiated %{pin_initiator} has sent a request to initiate your PIN reset. %{pin_initiator} ametuma ombi la kubadilisha PIN yako.

View File

@ -0,0 +1,862 @@
keys,en,sw,kam,kik,miji,luo,bor
initial_language_selection,"CON Welcome to Sarafu Network
%{first_language_set}
11. Next
00. Exit","CON Karibu Sarafu Network
%{first_language_set}
11. Mbele
00. Ondoka","CON Kalivu Network ya Sarafu
1. English
2. Kiswahili
3. Kikamba
3. Help","CON Karibu Sarafu Network
1. Githungu
2. Githweri
3. Uteithio","CON Karibu Sarafu Network
1. Chizungu
2. Chiswahili
3. Avizwa","CON Machiegni e network mar Sarafu
1. Dho Ngere
2. Dho oswayo
3. Kony","CON Karibu Sarafu Network
1. Afaan ferenji
2. Afaan kiswahili
3. Qarqars"
initial_pin_entry,CON Please enter a new four number PIN for your account.,CON Tafadhali weka pin mpya yenye nambari nne kwa akaunti yako,CON Tafadhali ikia pin yumbya ila ina namba inya kinanduni chaku,CON Ekera namba yaku ya thiri njeru ena numba enna.,CON Ika piniyo ya namba Ne kwa akaunti Yakwako.,CON Kiyie to ket namba ni mopondo e akaont ni.,CON Tafadhal pin hareti kekhae ka namba afuri fulaa akaunti kake
initial_pin_confirmation,CON Enter your four number PIN again,CON Weka PIN yako tena,CON Ikia PIN yaku ingi,CON Ekera namba yaku ya thiri ringi,CON Uyira Kwika pin kaheri.,CON Ket namba ni mopondo kendo,CON Mar dibii pin kekhae
enter_given_name,"CON Enter first name
0. Back",CON Weka jina lako la kwanza,CON Ikia isyitwa yaku ya mbee,CON Ekera retwa rwaku ria mbere,CON Ika dzinaro rakwanza.,CON Ket nyingi mokwongo,CON Makhaa kake ka karaa kor
enter_family_name,"CON Enter family name
0. Back","CON Weka jina lako la mwisho
0. Rudi","CON Ikia isyitwa yaku ya muthya
0. Syoka itina","CON Ekera ritwa rwaku ria mwisho
0. Coka thutha","CON Ika dzinaro ra mwisho
0. Uya Nyuma","CON Ket nyingi mogik.
0. Dog chien","CON Makhaa kake ka egee
0. Dhebii"
enter_date_of_birth,"CON Enter year of birth
0. Back","CON Weka mwaka wa kuzaliwa
0. Rudi","CON Ikia mwaka wa kusyawa
0. Syoka itina","CON Ekera mwaka waku wa guciarwo
0. Coka thutha","CON Ika mwaka wakuvyalwa
0. Uya Nyuma","CON Ket iki mar nyuol
0. Dog chien","CON Gan kake ka athdalat kor
0. Dheebi"
enter_gender,"CON Enter gender
1. Male
2. Female
3. Other
0. Back","CON Weka jinsia yako
1. Mwanaume
2. Mwanamke
3. Nyngine
0. Rudi","CON Ikia gender yaku
1. Mundume
2. Mundumuka
3. Ingi
0. Syoka itina","CON We mudurume kana mutumia
1.Mudurume
2. Mutumia
3. Ingi
0. Coka thutha","CON Ika kala Umulume ama Umuche au vingine.
1. Mulume
2. Muche
3. Vinjine
0. Uya Nyuma","CON Ket kit chwech mari
1. Dichuo
2. Dhako
3. Moko
0. Dog chien","CON Athin Dir mo Dubr
1. Dir
2. Dubr
3. Ka dibii
0. Dheebi"
enter_location,"CON Enter your location,
0. Back","CON Weka eneo lako
0. Rudi","CON Ikia utui waku kana location
0. Syoka itina","CON Ekera kuria uumete
0. Coka thutha","CON Ika enero wombolako.
0. Uya nyuma","CON Ket kumaidake
0. Dog chien","CON Fulaa athin kubat kor
0. Dhebii"
enter_products,"CON Please enter a product or service you offer
0. Back","CON Weka bidhaa ama huduma unauza
0. Rudi","CON Ikia syindu kana huduma ila unenganae
0. Syoka itina","CON Ekera indo kana wira uria urendia
0. Coka thutha","CON Ika Viya ama utu uhendao
0. Uya Nyuma","CON Ket gima iuso kata tich mitimo
0. Dog chien","CON Waan gurgurt okan namaa kenit khes khae
0. Dheebi"
start,"CON Balance %{account_balance} %{account_token_name}
1. Send
2. My Sarafu
3. My Account
4. Help","CON Salio %{account_balance} %{account_token_name}
1. Tuma
2. Sarafu yangu
3. Akaunti yangu
4. Usaidizi","CON Mbalansi kana utyalyo %{account_balance} %{account_token_name}
1. Tuma
2. Kinandu chakwa
3. Utethyo","CON Matigari %{account_balance} %{account_token_name}
1. Tuma
2. Akaunti yaku
3. Uteithio","CON Sazo %{account_balance} %{account_token_name}
1. Huma
2. Akaunti yangu
3. Avizwa","CON Ma Odong' %{account_balance} %{account_token_name}
1. Or
2. Akaont na
3. Kony","CON Salio %{account_balance} %{account_token_name}
1. Erg
2. Akaunti khiy
3. Qarqars"
enter_transaction_recipient,"CON Enter phone number
0. Back","CON Weka nambari ya simu
0. Rudi","CON Ikia namba ya simu
0. Syoka itina","CON Ikira namba ya thimu
0. Coka thutha","CON Ika namba yasimu.
0. Uya Nyuma","CON Ket nambani mar simu
0. Dog chien","CON Namba ta simuu kekhai
0. Dheebi"
enter_transaction_amount,"CON Enter amount
0. Back","CON Weka kiwango
0. Rudi","CON Ikia kiwango
0. Syoka itina","CON Ikira muigana
0. Coka thutha","CON Ika chaasi.
0. Uya nyuma","CON Ket giko mari
0. Dog chien","CON kiwango kekhai
0. Dheebi"
first_account_tokens_set,"CON Choose a number or symbol from your balances:
%{first_account_tokens_set}
0. Back
11. Next
00. Exit","CON Chagua nambari au ishara kutoka kwa salio zako:
%{first_account_tokens_set}
0. Rudi
11. Mbele
00. Ondoka","Sakua Sarafu:
%{token_list}
99. Thi mbee
00. Syoka itina","Shaghura Sarafu:
%{token_list}
99. Mbere
00. Coka thutha","Tsagula Sarafu:
%{token_list}
99. Enderera
00. Uya Nyuma","Yier Sarafu:
%{token_list}
99. Nyime
00. Dog chien","Chaqui Sarafu:
%{token_list}
99. Dhuur
00. Dheebi"
middle_account_tokens_set,"CON Choose a number or symbol from your balances:
%{middle_account_tokens_set}
11. Next
22. Previous
00. Exit","CON Chagua nambari au ishara kutoka kwa salio zako:
%{middle_account_tokens_set}
11. Mbele
22. Rudi
00. Ondoka","Sakura Sarafu:
%{token_list}
99. Thi mbee
00. Syoka itina","Shaghura Sarafu:
%{token_list}
99. Mbere
00. Cooka thutha","Tsagula Sarafu:
%{token_list}
99. Enderera
00. Uya Nyuma","Yier Sarafu:
%{token_list}
99. Nyime
00. Dog chien","Chaqui Sarafu:
%{token_list}
99. Dhuur
00. Dheebi"
last_account_tokens_set,"CON Choose a number or symbol from your balances:
%{last_account_tokens_set}
22. Previous
00. Exit","CON Chagua nambari au ishara kutoka kwa salio zako:
%{last_account_tokens_set}
22. Rudi
00. Ondoka","Sakura sarafu:
%{token_list}
00. Syoka itina","Sarafu:
%{token_list}
00. Cooka thutha","Tsagula Sarafu:
%{token_list}
00. Uya Nyuma","Yier Sarafu:
%{token_list}
00. Dog chien","Chagua Sarafu:
%{token_list}
00. Dheebi"
token_selection_pin_authorization.first,"CON %{token_data}
Enter pin to select:","CON %{token_data}
Weka nambari ya siri kuchagua:
0. Back","%{token_info}
Sakua kwa kwikia pin yaku:
0. Syoka itina","%{token_info}
Ekera pin yaku gushaghura:
0. Cooka thutha","%{token_info}
Ika piniyo kutsagula Sarafu:
0. Uya Nyuma","%{token_info}
Ket pin ni iyier:
0. Dog chien","%{token_info}
Pin kake khai akh dibii chaguat
0. Dheebi"
token_selection_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
account_management,"CON My account
1. My profile
2. Change language
3. Check balance
4. Check statement
5. PIN options
0. Back","CON Akaunti yangu
1. Wasifu wangu
2. Chagua lugha utakayotumia
3. Angalia salio
4. Angalia taarifa ya matumizi
5. Mipangilio ya nambari ya siri
0. Rudi","CON Kinandu Chakwa
1. Profile/wasifu wakwa
2. Sakua luka ila ukatumiaa
3. Syisya Mbalansi yaku
4. Syisya welesyo wa utumii
5. Chenja namba yaku ya siri
0. Syoka itina","CON Akaunti yakwa
1. Maritwa makwa
2. Shaghura rothiumu ukuhuthira
3. Rora matigari
4. Rora rugano rwa mahuthira
5. Chengia namba ya thiri
0. Coka","CON Akaunti yangu
1. Malagizo Gangu
2. Tsagula Luga Undohumira
3. Lola Sazo
4. Lola tarifa Za Mahumizi
5. Galuza Namba Fitse
0. Uya Nyuma","CON Akaont na
1. Nyanonro mara
2. Yier dhok midwatiyogo
3. Ngi midong go
4. N'gi chal mar akaont
5. Lok nambani mopondo
0. Dog chien","CON Akaunti khiy
1. Wasifu wangu
2. Afaan dubaad chaqui
3. laali balansi
4. Angalia taarifa ya matumizi
5. Gargarch namba
0. Dheebi"
metadata_management,"CON My profile
1. Edit name
2. Edit gender
3. Edit age
4. Edit location
5. Edit products
6. View my profile
0. Back","CON Wasifu wangu
1. Weka jina
2. Weka jinsia
3. Weka umri
4. Weka eneo
5. Weka bidhaa
6. Angalia wasifu wako
0. Rudi","CON Profile/Wasifu wakwa
1. Ikia isyitwa
2. Ikia jinsia/gender yaku
3. Ikia miaka yaku
4. Ikia utui waku
5. Ikia syindu ila utesaa
6. Sisya profile/wasifu waku
0. Syoka itina","CON Maondu maku
1. Ekera ritwa
2. Ekera kana we mundurume kana mutumia
3. Ekera miaka yaku
4. Ekera kuria uikaraga
5. Ikira kiria uendagia
6. Rora maundu maku
0. Coka thutha","CON Malagizo Gangu
1. Ika dzinaro
2. Ika kala umulume ama Umuche
3. Ika umuri
4. Ika eneo
5. Ika Miyo ama viya uguzavyo
6. Lola malagizo Gangu
0. Uya nyuma","CON Wasifu wangu
1. Ket nyingi
2. Ket kit chuech mari
3. Ket iki
4. Ket kumaidake
5. Ket gikmaiuso
6. Ng'i nyanonro mara
0. Dog chien","CON Wasifu wangu
1. Maqa kekhai
2. Naam dira mo dubr
3. Gan kekhai
4. Fulaa itgalt kai
5. Mih kai
6. Angalia wasifu wako
0. Dheebi"
display_user_metadata,"CON Your details are:
Name: %{full_name}
Gender: %{gender}
Age: %{age}
Location: %{location}
You sell: %{products}
0. Back","CON Wasifu wako una maelezo yafuatayo:
Jina: %{full_name}
Jinsia: %{gender}
Umri: %{age}
Eneo: %{location}
Unauza: %{products}
0. Rudi","CON Profile/Wasifu waku wina maelesyo aa:
Isyitwa: %{full_name}
Jinsia yaku/gender: %{gender}
Miaka yaku: %{age}
Utui/location yaku: %{location}
Syindu ila uta: %{products}
0. Syoka itina","CON Maundu maku mena rugano ruru:
Maretwa: %{full_name}
Mutumia kana muthuri: %{gender}
Miaka : %{age}
Kuria uikaraga : %{location}
Kiria uendagia : %{products}
0. Coka thutha","CON Malagizo gako gana moro uthuwizirao:
Dzina: %{full_name}
Umuche ama Mulume: %{gender}
Umuri: %{age}
Umbolako: %{location}
Miyo uguzayo: %{products}
0. Uya nyuma","CON Nyanonro mari en:
Nying: %{full_name}
Kit chuech: %{gender}
Iga: %{age}
Kumidake: %{location}
Gima iuso: %{products}
0. Dog chien","CON Wasifu wako una maelezo yafuatayo:
JinaMakha: %{full_name}
Jinsia: %{gender}
Gan: %{age}
Fulaa : %{location}
Maan gurgurt: %{products}
0. Dheebi"
select_preferred_language,"CON Choose language:
%{first_language_set}
0. Back
11. Next
00. Exit","CON Chagua lugha:
%{first_language_set}
0. Rudi
11. Mbele
00. Ondoka","CON Sakua luka
1. Kisungu
2. Kiswahili
3. Kikamba
0. Syoka itina","CON Caghura ruthiomi
1. Githungu
2. Githweri
0. Coka","CON Tsagula Luga
1. Kizungu
2. Kiswahili
0. Uya nyuma","CON Yier dhok
1. Dho Ngere
2. Dho Oswayo
0. Dog chien","CON Chagua lugha
1. Afaan ferenji
2. Afaan kiswahili
0. Dheebi"
retry_pin_entry,"CON Incorrect PIN entered,please try again. You have %{remaining_attempts} attempts remaining.
0. Back","CON Nambari uliyoweka si sahihi, jaribu tena. Una majaribio %{remaining_attempts} yaliyobaki.
0. Rudi","CON Namba ila wekiya iyaile, tata kwikia ingi. Tata mala %{remaining_attempts} nimo matyele.
0. Itina","CON Namba uikirite ti njega, geria ringi.Ni maita %{remaining_attempts} matigarete.
0. Gucoka thutha","CON Nambari fitse urioika seyo, jeza kaheri. Usere Majezo %{remaining_attempts} Gaserego.
0. Uya nyuma","CON Namba miketo oknikare, tem kendo. Idong gi temo di %{remaining_attempts} modong.
0. Chien","CON Namba at keket suninit,laal amalle.Nafaas kaitdheebit %tanaataf
0. Dheebi"
pin_management,"CON Pin options
1. Change PIN
2. Reset PIN
3. Guard PIN
0. Back","CON Pin options
1. Badilisha nambari yangu ya siri
2. Tuma ombili la kubadilisha nambari ya siri
3. Linda nambari ya siri
0. Rudi",,,,,
enter_current_pin.first,"CON Enter current PIN.
0. Back","CON Weka nambari ya siri.
0. Rudi","CON Ikia namba yaku ya siri.
0. Syoka itina","CON Ekera namba ya thiri
0. Coka thutha","CON Ika namba fitse.
0. Uya Nyuma","CON Ket nambani mopondo.
0. Dog chien","CON Namba ka namii imben kekhai
0. Dheebi"
enter_current_pin.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
enter_new_pin,"CON Enter your new four number PIN
0. Back","CON Weka nambari ya siri mpya
0. Rudi","CON Ikia namba yaku ya siri ila yumbya
0. Syoka itina","CON Ekera namba njeru ya thiri
0. coka thutha","CON Ika namba fitse mbisha
0. Uya nyuma","CON Ket namba mopondo maanyien.
0. Dog chien","CON Namba hareti ka namii imben kekhai
0. Dheebi"
new_pin_confirmation,"CON Enter your new four number PIN again
0. Back","CON Weka nambari yako ya siri tena
0. Rudi","CON Ikia namba yaku ya siri ingi
0. Syoka itina","CON Ekera namba yaku ya thiri renge
0. Coka thutha","CON Uyira kuika lwaphiri
0. Uya Nyuma","CON Ket nambani mopondo kendo
0. Dog chien","CON Namba hareti ka namii imben kekhai amalle
0. Dheebi"
reset_guarded_pin,"CON Enter phone number you are the guardian to reset their pin
0. Back","CON Weka nambari ya simu ili kutuma ombi la kubalisha nambari ya siri.
0. Rudi",,,,,
reset_guarded_pin_authorization.first,"CON Enter YOUR pin to confirm %{guarded_account_information}'s reset
0. Back","CON Weka nambari YAKO ya siri ili kudhibitisha ombi la kubadilisha nambari ya siri ya %{guarded_account_information}.
0. Rudi",,,,,
reset_guarded_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},,,,,
exit_pin_reset_initiated_success,"CON Success: You have initiated a PIN reset for %{guarded_account_information}
0. Back
9. Exit","CON Ombi lako la kubadili nambari ya siri ya %{guarded_account_information} limetumwa.
0. Rudi
9. Ondoka",,,,,
exit_not_authorized_for_pin_reset,"CON Failure: You are not authorized to reset that PIN. You must be a guardian!
0. Back
9. Exit","CON Huruhusiwi kutuma ombi la kubadilisha nambari ya siri.
0. Rudi
9. Ondoka",,,,,
guard_pin,"CON Pin guard
1. View guardians
2. Add guardian
3. Remove guardian
0. Back","CON Linda nambari ya siri
1. Walinzi wa namabari ya siri
2. Ongeza mlinzi
3. Ondoa mlinzi
0. Rudi",,,,,
guardian_list_pin_authorization.first,"CON Enter your pin to view set guardians
0. Back","CON Weka nambari yako ya siri ili kuona walinzi uliowaongeza
0. Rudi",,,,,
guardian_list_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},,,,,
guardian_list,"CON %{guardians_list}
0. Back
9. Exit","CON %{guardians_list}
0. Rudi
9. Ondoka",,,,,
add_guardian,"CON Enter phone number to add as pin reset guardian
0. Back","CON Weka nambari ya simu ili kuongeza mlinzi
0. Rudi",,,,,
add_guardian_pin_authorization.first,"CON Enter your pin to add %{guardian_information} as your PIN reset guardian
0. Back","CON Weka nambari YAKO ya siri ili kumwongeza %{guardian_information} kama mlinzi
0. Rudi",,,,,
add_guardian_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},,,,,
exit_guardian_addition_success,"CON Success: %{guardian_information} can now reset your PIN
0. Back
9. Exit","CON Ombi lako la kumwongeza: %{guardian_information} kama mlinzi limefanikiwa
0. Rudi
9. Ondoka",,,,,
exit_invalid_guardian_addition,"CON %{error_exit}
0. Back
9. Exit","CON %{error_exit}
0. Rudi
9. Ondoka",,,,,
remove_guardian,"CON Enter phone number to revoke guardianship:
0. Back","CON Weka nambari ya simu ili kuondoa mlinzi
0. Rudi",,,,,
remove_guardian_pin_authorization.first,"CON Enter your pin to remove %{guardian_information} as your PIN reset guardian
0. Back","CON Weka nambari YAKO ya siri ili kumwondoa %{guardian_information} kama mlinzi
0. Rudi",,,,,
remove_guardian_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},,,,,
exit_guardian_removal_success,"CON Success: %{guardian_information} PIN reset guardianship is revoked
0. Back
9. Exit","CON Ombi lako la kumwondoa: %{guardian_information} kama mlinzi limefanikiwa
0. Rudi
9. Ondoka",,,,,
exit_invalid_guardian_removal,"CON %{error_exit}
0. Back
9. Exit","CON %{error_exit}
0. Rudi
9. Ondoka",,,,,
transaction_pin_authorization.first,"CON %{recipient_information} will receive %{transaction_amount} %{token_symbol} from %{sender_information}.
Please enter your PIN to confirm.
0. Back","CON %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}.
Tafadhali weka nambari yako ya siri kudhibitisha.
0. Rudi","CON %{recipient_information} nukwata %{transaction_amount} %{token_symbol} kuma kwa %{sender_information}.
Tafadhali ikia namba yaku ya siri kuvitukithya.
0. Syoka itina","CON %{recipient_information} akuamukira %{transaction_amount} %{token_symbol} kuuma kwa %{sender_information}.
Ekera namba yaku ya thiri kuetekeria.
0. Coka thutha","CON %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}.
Unavoywa kuika nambayo fitse kugeluza.
0. Uya nyuma.","CON %{recipient_information} dhiyudo %{transaction_amount} %{token_symbol} kowuok kuom %{sender_information}.
Kiyie to ket nambani mopondo mondo iyie:
0. Dog chien","CON %{recipient_information} in argad%{transaction_amount} %{token_symbol} ir %{sender_information}.
Namba ka namii imben kekhai
0. Dheebi"
transaction_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
display_metadata_pin_authorization.first,"CON Please enter your PIN
0. Back","CON Tafadhali weka PIN yako
0. Rudi","CON Tafadhali ikia PIN yaku
0. Syoka itina","CON Ekera pin yaku
0. coka thutha","CON Unavoywa kuika namayo fitswe
0. Uya Nyuma","CON Kiyie to ket nambani mopondo
0. Dog chien","CON Namba ka namii imben kekhai
0. Dheebi"
display_metadata_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
account_balances_pin_authorization.first,"CON Please enter your PIN to view balances
0. Back","CON Tafadhali weka PIN yako kuona salio.
0. Rudi","CON Tafadhali ikia PIN yaku kwona utyalo.
0. Syoka itina","CON Ekera pin yaku kuona matigari maku
0. Coka ","CON Unavoywa namba fitswe kulola Sazo.
0. Uya nyuma","CON Kiyie to ket nambani mopondo mondo ine modong'
0. Dog chien","CON Namba ka namii imbeen kekhai ak balansi kake lalt
0. Dheebi"
account_balances_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
account_statement_pin_authorization.first,"CON Please enter your PIN to view statement
0. Back","CON Tafadhali weka PIN yako kuona taarifa ya matumizi.
0. Rudi","CON Tafadhali ikia PIN yaku kwona welesyo wa utumii.
0. Syoka itina","CON Ekera pin yaku kuona rugano rwa mahuthira maku
0. coka thutha","CON Unavoywa namba fitswe kupata maerezo ga mahumizi Gako.
0. Uya Nyuma","CON Kiyie to ket nambani mar siri mondo ine chenro mar tiyo.
0. Dog chien","CON Tafadhali weka PIN yako kuona taarifa ya matumizi.
0. Dheebi"
account_statement_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
name_edit_pin_authorization.first,"CON Please enter your PIN
0. Back","CON Tafadhali weka PIN yako
0. Rudi","CON Tafadhali ikia PIN yaku
0. Syoka itina","CON Ekera pin yaku
0. coka thutha","CON Unavoywa namba fitse
0. Uya Nyuma","CON Ket nambani mopondo
0. Dog chien","CON Namba ka namii imben kekhai
0. Dheebi"
name_edit_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
dob_edit_pin_authorization.first,"CON Please enter your PIN
0. Back","CON Tafadhali weka PIN yako
0. Rudi","CON Tafadhali ikia PIN yaku
0. Syoka itina","CON Ekera namba yaku ya thiri
0. Rudi","CON Unavoywa namba fitswe
0. Uya nyuma","CON Kiyie to ket nambani mopondo
0. Dog chien","CON Namba kake ka namii imbeen kekhai
0. Dheebi"
dob_edit_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
gender_edit_pin_authorization.first,"CON Please enter your PIN
0. Back","CON Tafadhali weka PIN yako
0. Rudi","CON Tafadhali ikia PIN yaku
0. Syoka itina","CON Ekera namba yaku ya thiri
0. coka thutha","CON Unavoywa namba fitswe
0. Uya nyuma","CON Kiyie to ket nambani mopondo
0. Dog chien","CON Namba kake ka namii imbeen kekhai
0. Dheebi"
gender_edit_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
location_edit_pin_authorization.first,"CON Please enter your PIN
0. Back","CON Tafadhali weka PIN yako
0. Rudi","CON Tafadhali ikia PIN yaku
0. Syoka itina","CON Ekera namba yaku ya thiri
0. Coka thutha","CON Unavoywa namba fitswe
0. Uya nyuma","CON Kiyie to ket nambani mopondo
0. Dog chien","CON Namba kake ka namii imbeen kekhai
0. Dheebi"
location_edit_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
products_edit_pin_authorization.first,"CON Please enter your PIN
0. Back","CON Tafadhali weka PIN yako
0. Rudi","CON Tafadhali ikia PIN yaku
0. Syoka itina","CON Ekera namba yaku ya thiri
0. Coka thutha","CON Unavoywa namba fitswe
0. Uya nyuma","CON Kiyie to ket nambani mopondo
0. Dog chien","CON Namba kake ka namii imbeen kekhai
0. Dheebi"
products_edit_pin_authorization.retry,%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry},%{retry_pin_entry}
account_balances.available_balance,"CON Your balances are as follows:
balance: %{available_balance} %{token_symbol}
0. Back","CON Salio zako ni zifuatazo:
salio: %{available_balance} %{token_symbol}
0. Rudi","CON Utyalo waku ni uu:
utyalo: %{available_balance} %{token_symbol}
0. Syoka itina","CON Matigari maku ni maya:
matigari: %{available_balance} %{token_symbol}
0. coka","CON Masazogo nidzavivyo gatuwiravyo:
Sazo: %{available_balance} %{token_symbol}
0. Uya Nyuma","CON Dong mari en:
Dong: %{available_balance} %{token_symbol}
0. Dog chien","CON Balansi kake akan
salio: %{available_balance} %{token_symbol}
0. Dheebi"
account_balances.with_fees,"CON Your balances are as follows:
balances: %{available_balance} %{token_symbol}
fees: %{tax} %{token_symbol}
0. Back","CON Salio zako ni zifuatazo:
salio: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
0. Rudi","CON Utyalo waku ni uu:
utyalo: %{available_balance} %{token_symbol}
tax/ushuru: %{tax} %{token_symbol}
0. Syoka itina","CON Matigari maku ni maya:
matigari: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
0. coka thutha","CON Masazogo ni gatuwirago:
Masazo: %{available_balance} %{token_symbol}
Ushuuru: %{tax} %{token_symbol}
0. Uya nyuma","CON Dong mari en:
Dong: %{available_balance} %{token_symbol}
osuru: %{tax} %{token_symbol}
0. Dog chien","CON Balansi kake akan
salio: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
0. Dheebi"
account_balances.with_rewards,"CON Your balances are as follows:
balance: %{available_balance} %{token_symbol}
fees: %{tax} %{token_symbol}
rewards: %{bonus} %{token_symbol}
0. Back","CON Salio zako ni zifuatazo:
salio: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
tuzo: %{bonus} %{token_symbol}
0. Rudi","CON Utyalo waku ni uu:
Utyalo: %{available_balance} %{token_symbol}
Tax/ushuru: %{tax} %{token_symbol}
muthinzio: %{bonus} %{token_symbol}
0. Syoka itina","CON Salio zako ni zifuatazo:
salio: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
tuzo: %{bonus} %{token_symbol}
0. coka thutha","CON Sazoro ni rituwiraro:
Sazo: %{available_balance} %{token_symbol}
Ushuuru: %{tax} %{token_symbol}
Zawadi: %{bonus} %{token_symbol}
0. Uya Nyuma","CON Dong mari en:
Dong: %{available_balance} %{token_symbol}
osuru: %{tax} %{token_symbol}
mich: %{bonus} %{token_symbol}
0. Dog chien","CON Balansi kake akan
salio: %{available_balance} %{token_symbol}
ushuru: %{tax} %{token_symbol}
tuzo: %{bonus} %{token_symbol}
0. Dheebi"
first_transaction_set,"CON %{first_transaction_set}
0. Back
11. Next
00. Exit","CON %{first_transaction_set}
0. Rudi
11. Mbele
00. Ondoka","CON %{first_transaction_set}
1. Mbee
00. Ondoka","CON %{first_transaction_set}
1. Mbere
00. uma","CON %{first_transaction_set}
1. Mbere
00. Uka","CON %{first_transaction_set}
1. Nyime
00. Wuogi","CON %{first_transaction_set}
1. Dhuur
00. Bai"
middle_transaction_set,"CON %{middle_transaction_set}
11. Next
22. Previous
00. Exit","CON %{middle_transaction_set}
11. Mbele
22. Rudi
00. Ondoka","CON %{middle_transaction_set}
1. Mbee
2. Itina
00. Ondoka","CON %{middle_transaction_set}
1. Mbere
2. coka thutha
00. Uma","CON %{middle_transaction_set}
1. Mbere
2. Uya nyuma
00. Uka","CON %{middle_transaction_set}
1. Nyime
2. Dog chien
00. Wuogi","CON %{middle_transaction_set}
1. Dhuur
2. Dheebi
00. Bai"
last_transaction_set,"CON %{last_transaction_set}
22. Previous
00. Exit","CON %{last_transaction_set}
22. Rudi
00. Ondoka","CON %{last_transaction_set}
2. Itina
00. Ondoka","CON %{last_transaction_set}
2. Coka thutha
00. Uma","CON %{last_transaction_set}
2. Uya Nyuma
00. Uka","CON %{last_transaction_set}
2. Dog chien
00. Wuogi","CON %{last_transaction_set}
2. Dhuur
00. Bai"
exit,END Thank you for using the service.,END Asante kwa kutumia huduma.,END Ni muvea kwa kutumia huduma ii.,END Thegio ni kuhuthira mutabo,END. Namvera kwa mahumizi ga ii huduma.,END Erokamano kuom tiyo kodwa.,END Asante kwa kutumia huduma.
exit_invalid_request,END Invalid request.,END Chaguo si sahihi.,END Usakuo waku uyaile.,END shaguro riaku ti riega,END. Tsagulo karisawa sawa,END Yiero okni kare,END Ka at chaquad suninit
exit_invalid_menu_option,"CON Invalid menu option. For help,call %{support_phone}.
00. Back
99. Exit","CON Chaguo lako sio sahihi. Kwa usaidizi piga simu %{support_phone}
00. Rudi
99. Ondoka","CON Usakuo waku uyaile. Kwa utethyo kuna simu %{support_phone}
00. Itina
99. Ondoka","CON Shaguro riaku ti riega.Kwa uteithio hura %{support_phone}
00. Coka thutha
99. Uma","CON Tsaguloro karisawa sawa. Kuavizwa piga %{support_phone}
00. Uya Nyuma
99. Uka","CON Yiero ni oknikare. Kuom kony go simu e %{support_phone}
00. Dog chien
99. Wuogi","CON Ka at chaqui suninit.qarqarsa simu dai%{support_phone}
00. Dheebi
99. Bai"
exit_invalid_input,"CON Invalid input. Nothing selected
00. Back
99. Exit","CON Chaguo lako halipatikani. Hakuna kilichochaguliwa.
00. Rudi
99. Ondoka","CON Usakuo waku wikwonekana.Vaii kindu kisakue.
00. Itina
99. Ondoka","CON Shaguro riaku ritironekana. Hatiri kindu washaghura.
00. Coka thutha
99. Uma","CON Tsaguloro karipatikana. Kakuna Kutsagurire chochosi.
00. Uya nyuma
99. Uka","CON Yiero ni okyudre. Onge gima iyiero.
00. Dog chien
99. Wuogi","CON Ka at chaguad injirt. oo
00. dheebi
99. Bai"
exit_pin_blocked,"END Your PIN has been blocked. For help, please call %{support_phone}.",END PIN yako imefungwa. Kwa usaidizi tafadhali piga simu %{support_phone}.,END PIN yaku niyavingwa. Kutethwa kuna simu ino %{support_phone}.,END PIN yaku niyahingwo. Kwa uteithio hura thimu %{support_phone}.,END. Namba fitse yakwako ifungwa. Kwa kuavizwa unaangwa upige simu %{support_phone}.,END Nambani mopondo olor. Kuom kony go simu e %{support_phone}.,END Pin kake yahidat. Qarqarsa simu dai %{support_phone}.
exit_invalid_pin,"END The PIN you have entered is invalid. PIN must consist of 4 digits. For help, call %{support_phone}.",END PIN uliyobonyeza sio sahihi. PIN lazima iwe na nambari nne. Kwa usaidizi piga simu %{support_phone}.,END PIN ila wekia iyaile. Ni lasima PIN ithiwe na namba inya. Kutethwa kuna namba ii %{support_phone}.,END PIN iria wekera tii njega. PIN nomoka ikorwo na namba inya. Kwa uteithio hura thimu %{support_phone}.,"END Namba fitse urohofya seyo, kaisawa. Namba fitswe inamalwa ikale na namba nee. Kwa kuvizwa, piga simu%{support_phone}.",END. Namba mopondo miketo oknikare. Nyaka obed gi nembni ang'wen. Kuom kony go simu e %{support_phone}.,END PIN ka at keket suninit. PIN Pin namba afuuri tatatu. Qarqarsa simu dai %{support_phone}.
exit_invalid_new_pin,"END The PIN you have entered is invalid. PIN must be different from your current PIN. For help, call %{support_phone}.",END PIN uliyobonyeza sio sahihi. PIN lazima iwe tofauti na pin yako ya sasa. Kwa usaidizi piga simu %{support_phone}.,END PIN ila wekia iyaile. PIN ni lasima ithiwe tofauti na pin yaku ya oyu. Kutethwa kuna namba ii %{support_phone}.,END PIN uria wekera ti njega. PIN nomohaka ikorwo na namba ndiganu na ya riu . Kwa uteithio hora thimu %{support_phone}.,END Namba fitswe uriohopya siyo ya karakara. Namba fitswe inahenzekana ikale itofauti na uhumirayo vivi. Kwa maavizo piga simu %{support_phone}.,END Namba mopondo miketo oknikare. Nyaka obed mopogore gi nambani mopondo masani. Kuom kony gochi e %{support_phone}.,END PIN ka at keket suninit.Pin kake walinfakaatin.Qarqars simu dai %{support_phone}.
exit_pin_mismatch,"END The new PIN does not match the one you entered. Please try again. For help, call %{support_phone}.",END PIN mpya na udhibitisho wa pin mpya hazilingani. Tafadhali jaribu tena. Kwa usaidizi piga simu %{support_phone}.,END PIN yumbya na uhakikisho wa pin yumbya syivwanene. Tafadhali tata ingi. Kutethwa kuna simu %{support_phone}.,END PIN njeru na pin ya guetekeria shitira hianana . Geria ringi. Kwa uteithio hora thimu %{support_phone}.,END Namba fitse uzdoinjiza kaikara kara na uriyohopya laphiri. Unavoywa ujeze kaheri. Kwa kuavizwa piga simu %{support_phone}.,GIKO. Namba mopondo miketo opogore gi manikuongo keto. Kiyie to ket kendo. Kuom kony gochi e %{support_phone}.,END PIN mpya na udhibitisho wa pin mpya hazilingani. Pin hareti ka at kekeet walinfakan. it dheebi amaale.Qarqars simu dai%{support_phone}.
exit_invalid_recipient,"CON Recipient's phone number is not registered or is invalid:
00. Retry
99. Exit","CON Mpokeaji wa nambari hapatikani au sio sahihi.
00. Jaribu tena
99. Ondoka","CON Mukwati wa namba ndokwatikana kana ii namba iyaile kana ti sahihi.
00. Tata ingi
99. Ondoka","CON Mpokeaji wa nambari hapatikani au sio sahihi.Namba ya mutumirwo ndiranyitikana kana ti njega
00. Geria ringi
99. Uma","CON Muphokezi wa namba kapatikana ama namba kai karakara.
00. Jeza Kaheri
99. Uka","CON Jayuto mar nambani okyudre kata oknikare.
00. Tem kendo
99. Wuogi","CON Mpokeaji wa nambari hapatikani au sio sahihi.
00.
99. Ondoka"
exit_successful_transaction,"CON Your request has been sent. %{recipient_information} will receive %{transaction_amount} %{token_symbol} from %{sender_information}.
00. Back
99. Exit","CON Ombi lako limetumwa. %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}.
00. Rudi
99. Ondoka","CON Woni waku niwatumwa. %{recipient_information} nukupokea %{transaction_amount} %{token_symbol} kuma kwa %{sender_information}.
00. Itina
99. Ondoka","CON Mahoya maku nimatomwo. %{recipient_information} akuamukira%{transaction_amount} %{token_symbol} kuma kwa %{sender_information}.
00. Coka
99. Uma","CON Mavoyogo gahumwa. %{recipient_information} undaphokera %{transaction_amount} %{token_symbol} kuombola kwa %{sender_information}.
00. Uya Nyuma
99. Uka","CON Kwayo ni oseor. %{recipient_information} oboyudo %{transaction_amount} %{token_symbol} kowuok kuom %{sender_information}.
00. Dog chien
99. Wuogi","CON Qarqar kake yaergad. %{recipient_information} inargat %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}.
00. Dheebi
99. Bai"
exit_insufficient_balance,"CON Payment of %{amount} %{token_symbol} to %{recipient_information} has failed due to insufficient balance.
Your Sarafu-Network balances is: %{token_balance}
00. Back
99. Exit","CON Malipo ya %{amount} %{token_symbol} kwa %{recipient_information} halijakamilika kwa sababu salio lako haitoshi.
Akaunti yako ya Sarafu ina salio ifuatayo: %{token_balance}
00. Rudi
99. Ondoka","CON Ndivi ya %{amount} %{token_symbol} kwa %{recipient_information} inavitukithwa nundu utyalyo waku ni munini.
Kinandu chaku cha Sarafu kina utyalo uu: %{token_balance}
00. Itina
99. Ondoka","CON Marehi ma %{amount} %{token_symbol} kwa %{recipient_information} matinarekereka tondu matigari maku matiraigana.
Akaunti yako ya Sarafu ina salio ifuatayo: %{token_balance}
00. Coka
99. Uma","CON Maripho ga %{amount} %{token_symbol} kwa %{recipient_information} Karidzangwe kukamirika Kwaukala sazoro Karitosha.
Akauntiyo vivi ina sazo dza rituwiranavyo: %{token_balance}
00. Uya nyuma
99. Uka","CON Chudo mar %{amount} %{token_symbol} kuom %{recipient_information} okotieki nikech dong ni okrom.
Akaont ni mar Sarafu ni gi dong mar: %{token_balance}
00. Dog chien
99. Wuogi","CON Malipo ka%{amount} %{token_symbol} kwa %{recipient_information} Inkamilikee balansi kake ingau
Akaunti kake balansi akan kabd: %{token_balance}
00. Dheebi
99. Bai"
exit_successful_token_selection,"CON Success! %{token_symbol} is your active Sarafu.
00. Back
99. Exit","CON Chaguo lako limekamilika, %{token_symbol} ni sarafu itakayotumika.
00. Rudi
99. Ondoka",,,,,
invalid_service_code,Please dial %{valid_service_code} to access Sarafu Network,Bonyeza %{valid_service_code} kutumia mtandao wa Sarafu,Vinyia %{valid_service_code} kutumia mutandao wa Sarafu,Hihinya%{valid_service_code} kuhudhira mutabo wa Sarafu,Hofya %{valid_service_code} Kuhumira Mutandao wa sarafu,Dii %{valid_service_code} mondo iti gi Sarafu,Bonyeza %{valid_service_code} kutumia mtandao wa Sarafu
help,"CON For assistance call %{support_phone}
00. Back
99. Exit","CON Kwa usaidizi piga simu %{support_phone}
0. Rudi
9. Ondoka","CON Kwa utethyo kuna simu %{support_phone}
0. Itina
9. Ondoka","CON Kwa uteithio hora thimu %{support_phone}
0. Coka
9. Uma","CON Kwa Kuavizwa piga simu %{support_phone}
0. Uya nyuma
9. Uka","CON Kuom kony go simu e %{support_phone}
0. Dog chien
9. Wuogi","CON Qarqars simu dai%{support_phone}
0. Dheebi
9. Bai"
complete,"CON Your request has been sent. You will receive an SMS shortly.
00. Back
99. Exit","CON Ombi lako limetumwa. Utapokea uthibitishaji wa SMS kwa muda mfupi.
00. Rudi
99. Ondoka","CON Woni waku niwatumwa. Nukwata SMS ya kwonya ivinda ite yasa.
00. Itina
99. Ondoka","CON Mahoya maku nimatomwo. Niukuamukira SMS ya guitikirika ihinda ikuhi .
00. Coka
99. Uma","CON Vyoyoro rihumwa. Undaphokera Uthibitishaji wa SMS kwa muda mufuhi.
00. Uya nyuma
99. Uka","CON Kwayo ni oseor. Iboyudo mesej mar ote ni bang' saa matin.
00. Dog chien
99. Wuogi","CON Qarqars kake yaergad. Utapokea uthibitishaji wa SMS kwa muda mfupi.
00. Dheebi
99. Bai"
account_creation_prompt,END Your account is being created. You will receive an SMS when your account is ready.,END Akaunti yako ya Sarafu inatayarishwa. Utapokea ujumbe wa SMS akaunti yako ikiwa tayari.,END Akaunti yako ya Sarafu yendeye usovwa. Nukwata SMS akaunti yaku yasovwa.,END Akaunti yaku ya Sarafu niiraharirio.Niugutumirwo SMS akauti yaku ya rikio kuharirio,END Akauntiyo ya sarafu idzikoni. Undaphokera ujumbe wa SMS ichikala tayari.,END Akaont ni mar Sarafu iloso. Iboyudo mesej ka akaont ni otieki.,END Akaunti yako ya Sarafu inatayarishwa. Utapokea ujumbe wa SMS akaunti yako ikiwa tayari.
initial_middle_language_set,"CON Choose language:
%{middle_language_set}
11. Next
22. Previous
00. Exit","CON Chagua lugha:
%{middle_language_set}
11. Mbele
22. Rudi
00. Ondoka",,,,,
initial_last_language_set,"CON Choose language:
%{last_language_set}
22. Previous
00. Exit","CON Choose language:
%{last_language_set}
22. Rudi
00. Ondoka",,,,,
middle_language_set,"CON Choose language:
%{middle_language_set}
11. Next
22. Previous
00. Exit","CON Chagua lugha:
%{middle_language_set}
11. Mbele
22. Rudi
00. Ondoka",,,,,
last_language_set,"CON Choose language:
%{last_language_set}
22. Previous
00. Exit","CON Choose language:
%{last_language_set}
22. Rudi
00. Ondoka",,,,,
1 keys en sw kam kik miji luo bor
2 initial_language_selection CON Welcome to Sarafu Network %{first_language_set} 11. Next 00. Exit CON Karibu Sarafu Network %{first_language_set} 11. Mbele 00. Ondoka CON Kalivu Network ya Sarafu 1. English 2. Kiswahili 3. Kikamba 3. Help CON Karibu Sarafu Network 1. Githungu 2. Githweri 3. Uteithio CON Karibu Sarafu Network 1. Chizungu 2. Chiswahili 3. Avizwa CON Machiegni e network mar Sarafu 1. Dho Ngere 2. Dho oswayo 3. Kony CON Karibu Sarafu Network 1. Afaan ferenji 2. Afaan kiswahili 3. Qarqars
3 initial_pin_entry CON Please enter a new four number PIN for your account. CON Tafadhali weka pin mpya yenye nambari nne kwa akaunti yako CON Tafadhali ikia pin yumbya ila ina namba inya kinanduni chaku CON Ekera namba yaku ya thiri njeru ena numba enna. CON Ika piniyo ya namba Ne kwa akaunti Yakwako. CON Kiyie to ket namba ni mopondo e akaont ni. CON Tafadhal pin hareti kekhae ka namba afuri fulaa akaunti kake
4 initial_pin_confirmation CON Enter your four number PIN again CON Weka PIN yako tena CON Ikia PIN yaku ingi CON Ekera namba yaku ya thiri ringi CON Uyira Kwika pin kaheri. CON Ket namba ni mopondo kendo CON Mar dibii pin kekhae
5 enter_given_name CON Enter first name 0. Back CON Weka jina lako la kwanza CON Ikia isyitwa yaku ya mbee CON Ekera retwa rwaku ria mbere CON Ika dzinaro rakwanza. CON Ket nyingi mokwongo CON Makhaa kake ka karaa kor
6 enter_family_name CON Enter family name 0. Back CON Weka jina lako la mwisho 0. Rudi CON Ikia isyitwa yaku ya muthya 0. Syoka itina CON Ekera ritwa rwaku ria mwisho 0. Coka thutha CON Ika dzinaro ra mwisho 0. Uya Nyuma CON Ket nyingi mogik. 0. Dog chien CON Makhaa kake ka egee 0. Dhebii
7 enter_date_of_birth CON Enter year of birth 0. Back CON Weka mwaka wa kuzaliwa 0. Rudi CON Ikia mwaka wa kusyawa 0. Syoka itina CON Ekera mwaka waku wa guciarwo 0. Coka thutha CON Ika mwaka wakuvyalwa 0. Uya Nyuma CON Ket iki mar nyuol 0. Dog chien CON Gan kake ka athdalat kor 0. Dheebi
8 enter_gender CON Enter gender 1. Male 2. Female 3. Other 0. Back CON Weka jinsia yako 1. Mwanaume 2. Mwanamke 3. Nyngine 0. Rudi CON Ikia gender yaku 1. Mundume 2. Mundumuka 3. Ingi 0. Syoka itina CON We mudurume kana mutumia 1.Mudurume 2. Mutumia 3. Ingi 0. Coka thutha CON Ika kala Umulume ama Umuche au vingine. 1. Mulume 2. Muche 3. Vinjine 0. Uya Nyuma CON Ket kit chwech mari 1. Dichuo 2. Dhako 3. Moko 0. Dog chien CON Athin Dir mo Dubr 1. Dir 2. Dubr 3. Ka dibii 0. Dheebi
9 enter_location CON Enter your location, 0. Back CON Weka eneo lako 0. Rudi CON Ikia utui waku kana location 0. Syoka itina CON Ekera kuria uumete 0. Coka thutha CON Ika enero wombolako. 0. Uya nyuma CON Ket kumaidake 0. Dog chien CON Fulaa athin kubat kor 0. Dhebii
10 enter_products CON Please enter a product or service you offer 0. Back CON Weka bidhaa ama huduma unauza 0. Rudi CON Ikia syindu kana huduma ila unenganae 0. Syoka itina CON Ekera indo kana wira uria urendia 0. Coka thutha CON Ika Viya ama utu uhendao 0. Uya Nyuma CON Ket gima iuso kata tich mitimo 0. Dog chien CON Waan gurgurt okan namaa kenit khes khae 0. Dheebi
11 start CON Balance %{account_balance} %{account_token_name} 1. Send 2. My Sarafu 3. My Account 4. Help CON Salio %{account_balance} %{account_token_name} 1. Tuma 2. Sarafu yangu 3. Akaunti yangu 4. Usaidizi CON Mbalansi kana utyalyo %{account_balance} %{account_token_name} 1. Tuma 2. Kinandu chakwa 3. Utethyo CON Matigari %{account_balance} %{account_token_name} 1. Tuma 2. Akaunti yaku 3. Uteithio CON Sazo %{account_balance} %{account_token_name} 1. Huma 2. Akaunti yangu 3. Avizwa CON Ma Odong' %{account_balance} %{account_token_name} 1. Or 2. Akaont na 3. Kony CON Salio %{account_balance} %{account_token_name} 1. Erg 2. Akaunti khiy 3. Qarqars
12 enter_transaction_recipient CON Enter phone number 0. Back CON Weka nambari ya simu 0. Rudi CON Ikia namba ya simu 0. Syoka itina CON Ikira namba ya thimu 0. Coka thutha CON Ika namba yasimu. 0. Uya Nyuma CON Ket nambani mar simu 0. Dog chien CON Namba ta simuu kekhai 0. Dheebi
13 enter_transaction_amount CON Enter amount 0. Back CON Weka kiwango 0. Rudi CON Ikia kiwango 0. Syoka itina CON Ikira muigana 0. Coka thutha CON Ika chaasi. 0. Uya nyuma CON Ket giko mari 0. Dog chien CON kiwango kekhai 0. Dheebi
14 first_account_tokens_set CON Choose a number or symbol from your balances: %{first_account_tokens_set} 0. Back 11. Next 00. Exit CON Chagua nambari au ishara kutoka kwa salio zako: %{first_account_tokens_set} 0. Rudi 11. Mbele 00. Ondoka Sakua Sarafu: %{token_list} 99. Thi mbee 00. Syoka itina Shaghura Sarafu: %{token_list} 99. Mbere 00. Coka thutha Tsagula Sarafu: %{token_list} 99. Enderera 00. Uya Nyuma Yier Sarafu: %{token_list} 99. Nyime 00. Dog chien Chaqui Sarafu: %{token_list} 99. Dhuur 00. Dheebi
15 middle_account_tokens_set CON Choose a number or symbol from your balances: %{middle_account_tokens_set} 11. Next 22. Previous 00. Exit CON Chagua nambari au ishara kutoka kwa salio zako: %{middle_account_tokens_set} 11. Mbele 22. Rudi 00. Ondoka Sakura Sarafu: %{token_list} 99. Thi mbee 00. Syoka itina Shaghura Sarafu: %{token_list} 99. Mbere 00. Cooka thutha Tsagula Sarafu: %{token_list} 99. Enderera 00. Uya Nyuma Yier Sarafu: %{token_list} 99. Nyime 00. Dog chien Chaqui Sarafu: %{token_list} 99. Dhuur 00. Dheebi
16 last_account_tokens_set CON Choose a number or symbol from your balances: %{last_account_tokens_set} 22. Previous 00. Exit CON Chagua nambari au ishara kutoka kwa salio zako: %{last_account_tokens_set} 22. Rudi 00. Ondoka Sakura sarafu: %{token_list} 00. Syoka itina Sarafu: %{token_list} 00. Cooka thutha Tsagula Sarafu: %{token_list} 00. Uya Nyuma Yier Sarafu: %{token_list} 00. Dog chien Chagua Sarafu: %{token_list} 00. Dheebi
17 token_selection_pin_authorization.first CON %{token_data} Enter pin to select: CON %{token_data} Weka nambari ya siri kuchagua: 0. Back %{token_info} Sakua kwa kwikia pin yaku: 0. Syoka itina %{token_info} Ekera pin yaku gushaghura: 0. Cooka thutha %{token_info} Ika piniyo kutsagula Sarafu: 0. Uya Nyuma %{token_info} Ket pin ni iyier: 0. Dog chien %{token_info} Pin kake khai akh dibii chaguat 0. Dheebi
18 token_selection_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
19 account_management CON My account 1. My profile 2. Change language 3. Check balance 4. Check statement 5. PIN options 0. Back CON Akaunti yangu 1. Wasifu wangu 2. Chagua lugha utakayotumia 3. Angalia salio 4. Angalia taarifa ya matumizi 5. Mipangilio ya nambari ya siri 0. Rudi CON Kinandu Chakwa 1. Profile/wasifu wakwa 2. Sakua luka ila ukatumiaa 3. Syisya Mbalansi yaku 4. Syisya welesyo wa utumii 5. Chenja namba yaku ya siri 0. Syoka itina CON Akaunti yakwa 1. Maritwa makwa 2. Shaghura rothiumu ukuhuthira 3. Rora matigari 4. Rora rugano rwa mahuthira 5. Chengia namba ya thiri 0. Coka CON Akaunti yangu 1. Malagizo Gangu 2. Tsagula Luga Undohumira 3. Lola Sazo 4. Lola tarifa Za Mahumizi 5. Galuza Namba Fitse 0. Uya Nyuma CON Akaont na 1. Nyanonro mara 2. Yier dhok midwatiyogo 3. Ngi midong go 4. N'gi chal mar akaont 5. Lok nambani mopondo 0. Dog chien CON Akaunti khiy 1. Wasifu wangu 2. Afaan dubaad chaqui 3. laali balansi 4. Angalia taarifa ya matumizi 5. Gargarch namba 0. Dheebi
20 metadata_management CON My profile 1. Edit name 2. Edit gender 3. Edit age 4. Edit location 5. Edit products 6. View my profile 0. Back CON Wasifu wangu 1. Weka jina 2. Weka jinsia 3. Weka umri 4. Weka eneo 5. Weka bidhaa 6. Angalia wasifu wako 0. Rudi CON Profile/Wasifu wakwa 1. Ikia isyitwa 2. Ikia jinsia/gender yaku 3. Ikia miaka yaku 4. Ikia utui waku 5. Ikia syindu ila utesaa 6. Sisya profile/wasifu waku 0. Syoka itina CON Maondu maku 1. Ekera ritwa 2. Ekera kana we mundurume kana mutumia 3. Ekera miaka yaku 4. Ekera kuria uikaraga 5. Ikira kiria uendagia 6. Rora maundu maku 0. Coka thutha CON Malagizo Gangu 1. Ika dzinaro 2. Ika kala umulume ama Umuche 3. Ika umuri 4. Ika eneo 5. Ika Miyo ama viya uguzavyo 6. Lola malagizo Gangu 0. Uya nyuma CON Wasifu wangu 1. Ket nyingi 2. Ket kit chuech mari 3. Ket iki 4. Ket kumaidake 5. Ket gikmaiuso 6. Ng'i nyanonro mara 0. Dog chien CON Wasifu wangu 1. Maqa kekhai 2. Naam dira mo dubr 3. Gan kekhai 4. Fulaa itgalt kai 5. Mih kai 6. Angalia wasifu wako 0. Dheebi
21 display_user_metadata CON Your details are: Name: %{full_name} Gender: %{gender} Age: %{age} Location: %{location} You sell: %{products} 0. Back CON Wasifu wako una maelezo yafuatayo: Jina: %{full_name} Jinsia: %{gender} Umri: %{age} Eneo: %{location} Unauza: %{products} 0. Rudi CON Profile/Wasifu waku wina maelesyo aa: Isyitwa: %{full_name} Jinsia yaku/gender: %{gender} Miaka yaku: %{age} Utui/location yaku: %{location} Syindu ila uta: %{products} 0. Syoka itina CON Maundu maku mena rugano ruru: Maretwa: %{full_name} Mutumia kana muthuri: %{gender} Miaka : %{age} Kuria uikaraga : %{location} Kiria uendagia : %{products} 0. Coka thutha CON Malagizo gako gana moro uthuwizirao: Dzina: %{full_name} Umuche ama Mulume: %{gender} Umuri: %{age} Umbolako: %{location} Miyo uguzayo: %{products} 0. Uya nyuma CON Nyanonro mari en: Nying: %{full_name} Kit chuech: %{gender} Iga: %{age} Kumidake: %{location} Gima iuso: %{products} 0. Dog chien CON Wasifu wako una maelezo yafuatayo: JinaMakha: %{full_name} Jinsia: %{gender} Gan: %{age} Fulaa : %{location} Maan gurgurt: %{products} 0. Dheebi
22 select_preferred_language CON Choose language: %{first_language_set} 0. Back 11. Next 00. Exit CON Chagua lugha: %{first_language_set} 0. Rudi 11. Mbele 00. Ondoka CON Sakua luka 1. Kisungu 2. Kiswahili 3. Kikamba 0. Syoka itina CON Caghura ruthiomi 1. Githungu 2. Githweri 0. Coka CON Tsagula Luga 1. Kizungu 2. Kiswahili 0. Uya nyuma CON Yier dhok 1. Dho Ngere 2. Dho Oswayo 0. Dog chien CON Chagua lugha 1. Afaan ferenji 2. Afaan kiswahili 0. Dheebi
23 retry_pin_entry CON Incorrect PIN entered,please try again. You have %{remaining_attempts} attempts remaining. 0. Back CON Nambari uliyoweka si sahihi, jaribu tena. Una majaribio %{remaining_attempts} yaliyobaki. 0. Rudi CON Namba ila wekiya iyaile, tata kwikia ingi. Tata mala %{remaining_attempts} nimo matyele. 0. Itina CON Namba uikirite ti njega, geria ringi.Ni maita %{remaining_attempts} matigarete. 0. Gucoka thutha CON Nambari fitse urioika seyo, jeza kaheri. Usere Majezo %{remaining_attempts} Gaserego. 0. Uya nyuma CON Namba miketo oknikare, tem kendo. Idong gi temo di %{remaining_attempts} modong. 0. Chien CON Namba at keket suninit,laal amalle.Nafaas kaitdheebit %tanaataf 0. Dheebi
24 pin_management CON Pin options 1. Change PIN 2. Reset PIN 3. Guard PIN 0. Back CON Pin options 1. Badilisha nambari yangu ya siri 2. Tuma ombili la kubadilisha nambari ya siri 3. Linda nambari ya siri 0. Rudi
25 enter_current_pin.first CON Enter current PIN. 0. Back CON Weka nambari ya siri. 0. Rudi CON Ikia namba yaku ya siri. 0. Syoka itina CON Ekera namba ya thiri 0. Coka thutha CON Ika namba fitse. 0. Uya Nyuma CON Ket nambani mopondo. 0. Dog chien CON Namba ka namii imben kekhai 0. Dheebi
26 enter_current_pin.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
27 enter_new_pin CON Enter your new four number PIN 0. Back CON Weka nambari ya siri mpya 0. Rudi CON Ikia namba yaku ya siri ila yumbya 0. Syoka itina CON Ekera namba njeru ya thiri 0. coka thutha CON Ika namba fitse mbisha 0. Uya nyuma CON Ket namba mopondo maanyien. 0. Dog chien CON Namba hareti ka namii imben kekhai 0. Dheebi
28 new_pin_confirmation CON Enter your new four number PIN again 0. Back CON Weka nambari yako ya siri tena 0. Rudi CON Ikia namba yaku ya siri ingi 0. Syoka itina CON Ekera namba yaku ya thiri renge 0. Coka thutha CON Uyira kuika lwaphiri 0. Uya Nyuma CON Ket nambani mopondo kendo 0. Dog chien CON Namba hareti ka namii imben kekhai amalle 0. Dheebi
29 reset_guarded_pin CON Enter phone number you are the guardian to reset their pin 0. Back CON Weka nambari ya simu ili kutuma ombi la kubalisha nambari ya siri. 0. Rudi
30 reset_guarded_pin_authorization.first CON Enter YOUR pin to confirm %{guarded_account_information}'s reset 0. Back CON Weka nambari YAKO ya siri ili kudhibitisha ombi la kubadilisha nambari ya siri ya %{guarded_account_information}. 0. Rudi
31 reset_guarded_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry}
32 exit_pin_reset_initiated_success CON Success: You have initiated a PIN reset for %{guarded_account_information} 0. Back 9. Exit CON Ombi lako la kubadili nambari ya siri ya %{guarded_account_information} limetumwa. 0. Rudi 9. Ondoka
33 exit_not_authorized_for_pin_reset CON Failure: You are not authorized to reset that PIN. You must be a guardian! 0. Back 9. Exit CON Huruhusiwi kutuma ombi la kubadilisha nambari ya siri. 0. Rudi 9. Ondoka
34 guard_pin CON Pin guard 1. View guardians 2. Add guardian 3. Remove guardian 0. Back CON Linda nambari ya siri 1. Walinzi wa namabari ya siri 2. Ongeza mlinzi 3. Ondoa mlinzi 0. Rudi
35 guardian_list_pin_authorization.first CON Enter your pin to view set guardians 0. Back CON Weka nambari yako ya siri ili kuona walinzi uliowaongeza 0. Rudi
36 guardian_list_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry}
37 guardian_list CON %{guardians_list} 0. Back 9. Exit CON %{guardians_list} 0. Rudi 9. Ondoka
38 add_guardian CON Enter phone number to add as pin reset guardian 0. Back CON Weka nambari ya simu ili kuongeza mlinzi 0. Rudi
39 add_guardian_pin_authorization.first CON Enter your pin to add %{guardian_information} as your PIN reset guardian 0. Back CON Weka nambari YAKO ya siri ili kumwongeza %{guardian_information} kama mlinzi 0. Rudi
40 add_guardian_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry}
41 exit_guardian_addition_success CON Success: %{guardian_information} can now reset your PIN 0. Back 9. Exit CON Ombi lako la kumwongeza: %{guardian_information} kama mlinzi limefanikiwa 0. Rudi 9. Ondoka
42 exit_invalid_guardian_addition CON %{error_exit} 0. Back 9. Exit CON %{error_exit} 0. Rudi 9. Ondoka
43 remove_guardian CON Enter phone number to revoke guardianship: 0. Back CON Weka nambari ya simu ili kuondoa mlinzi 0. Rudi
44 remove_guardian_pin_authorization.first CON Enter your pin to remove %{guardian_information} as your PIN reset guardian 0. Back CON Weka nambari YAKO ya siri ili kumwondoa %{guardian_information} kama mlinzi 0. Rudi
45 remove_guardian_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry}
46 exit_guardian_removal_success CON Success: %{guardian_information} PIN reset guardianship is revoked 0. Back 9. Exit CON Ombi lako la kumwondoa: %{guardian_information} kama mlinzi limefanikiwa 0. Rudi 9. Ondoka
47 exit_invalid_guardian_removal CON %{error_exit} 0. Back 9. Exit CON %{error_exit} 0. Rudi 9. Ondoka
48 transaction_pin_authorization.first CON %{recipient_information} will receive %{transaction_amount} %{token_symbol} from %{sender_information}. Please enter your PIN to confirm. 0. Back CON %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}. Tafadhali weka nambari yako ya siri kudhibitisha. 0. Rudi CON %{recipient_information} nukwata %{transaction_amount} %{token_symbol} kuma kwa %{sender_information}. Tafadhali ikia namba yaku ya siri kuvitukithya. 0. Syoka itina CON %{recipient_information} akuamukira %{transaction_amount} %{token_symbol} kuuma kwa %{sender_information}. Ekera namba yaku ya thiri kuetekeria. 0. Coka thutha CON %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}. Unavoywa kuika nambayo fitse kugeluza. 0. Uya nyuma. CON %{recipient_information} dhiyudo %{transaction_amount} %{token_symbol} kowuok kuom %{sender_information}. Kiyie to ket nambani mopondo mondo iyie: 0. Dog chien CON %{recipient_information} in argad%{transaction_amount} %{token_symbol} ir %{sender_information}. Namba ka namii imben kekhai 0. Dheebi
49 transaction_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
50 display_metadata_pin_authorization.first CON Please enter your PIN 0. Back CON Tafadhali weka PIN yako 0. Rudi CON Tafadhali ikia PIN yaku 0. Syoka itina CON Ekera pin yaku 0. coka thutha CON Unavoywa kuika namayo fitswe 0. Uya Nyuma CON Kiyie to ket nambani mopondo 0. Dog chien CON Namba ka namii imben kekhai 0. Dheebi
51 display_metadata_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
52 account_balances_pin_authorization.first CON Please enter your PIN to view balances 0. Back CON Tafadhali weka PIN yako kuona salio. 0. Rudi CON Tafadhali ikia PIN yaku kwona utyalo. 0. Syoka itina CON Ekera pin yaku kuona matigari maku 0. Coka CON Unavoywa namba fitswe kulola Sazo. 0. Uya nyuma CON Kiyie to ket nambani mopondo mondo ine modong' 0. Dog chien CON Namba ka namii imbeen kekhai ak balansi kake lalt 0. Dheebi
53 account_balances_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
54 account_statement_pin_authorization.first CON Please enter your PIN to view statement 0. Back CON Tafadhali weka PIN yako kuona taarifa ya matumizi. 0. Rudi CON Tafadhali ikia PIN yaku kwona welesyo wa utumii. 0. Syoka itina CON Ekera pin yaku kuona rugano rwa mahuthira maku 0. coka thutha CON Unavoywa namba fitswe kupata maerezo ga mahumizi Gako. 0. Uya Nyuma CON Kiyie to ket nambani mar siri mondo ine chenro mar tiyo. 0. Dog chien CON Tafadhali weka PIN yako kuona taarifa ya matumizi. 0. Dheebi
55 account_statement_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
56 name_edit_pin_authorization.first CON Please enter your PIN 0. Back CON Tafadhali weka PIN yako 0. Rudi CON Tafadhali ikia PIN yaku 0. Syoka itina CON Ekera pin yaku 0. coka thutha CON Unavoywa namba fitse 0. Uya Nyuma CON Ket nambani mopondo 0. Dog chien CON Namba ka namii imben kekhai 0. Dheebi
57 name_edit_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
58 dob_edit_pin_authorization.first CON Please enter your PIN 0. Back CON Tafadhali weka PIN yako 0. Rudi CON Tafadhali ikia PIN yaku 0. Syoka itina CON Ekera namba yaku ya thiri 0. Rudi CON Unavoywa namba fitswe 0. Uya nyuma CON Kiyie to ket nambani mopondo 0. Dog chien CON Namba kake ka namii imbeen kekhai 0. Dheebi
59 dob_edit_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
60 gender_edit_pin_authorization.first CON Please enter your PIN 0. Back CON Tafadhali weka PIN yako 0. Rudi CON Tafadhali ikia PIN yaku 0. Syoka itina CON Ekera namba yaku ya thiri 0. coka thutha CON Unavoywa namba fitswe 0. Uya nyuma CON Kiyie to ket nambani mopondo 0. Dog chien CON Namba kake ka namii imbeen kekhai 0. Dheebi
61 gender_edit_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
62 location_edit_pin_authorization.first CON Please enter your PIN 0. Back CON Tafadhali weka PIN yako 0. Rudi CON Tafadhali ikia PIN yaku 0. Syoka itina CON Ekera namba yaku ya thiri 0. Coka thutha CON Unavoywa namba fitswe 0. Uya nyuma CON Kiyie to ket nambani mopondo 0. Dog chien CON Namba kake ka namii imbeen kekhai 0. Dheebi
63 location_edit_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
64 products_edit_pin_authorization.first CON Please enter your PIN 0. Back CON Tafadhali weka PIN yako 0. Rudi CON Tafadhali ikia PIN yaku 0. Syoka itina CON Ekera namba yaku ya thiri 0. Coka thutha CON Unavoywa namba fitswe 0. Uya nyuma CON Kiyie to ket nambani mopondo 0. Dog chien CON Namba kake ka namii imbeen kekhai 0. Dheebi
65 products_edit_pin_authorization.retry %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry} %{retry_pin_entry}
66 account_balances.available_balance CON Your balances are as follows: balance: %{available_balance} %{token_symbol} 0. Back CON Salio zako ni zifuatazo: salio: %{available_balance} %{token_symbol} 0. Rudi CON Utyalo waku ni uu: utyalo: %{available_balance} %{token_symbol} 0. Syoka itina CON Matigari maku ni maya: matigari: %{available_balance} %{token_symbol} 0. coka CON Masazogo nidzavivyo gatuwiravyo: Sazo: %{available_balance} %{token_symbol} 0. Uya Nyuma CON Dong mari en: Dong: %{available_balance} %{token_symbol} 0. Dog chien CON Balansi kake akan salio: %{available_balance} %{token_symbol} 0. Dheebi
67 account_balances.with_fees CON Your balances are as follows: balances: %{available_balance} %{token_symbol} fees: %{tax} %{token_symbol} 0. Back CON Salio zako ni zifuatazo: salio: %{available_balance} %{token_symbol} ushuru: %{tax} %{token_symbol} 0. Rudi CON Utyalo waku ni uu: utyalo: %{available_balance} %{token_symbol} tax/ushuru: %{tax} %{token_symbol} 0. Syoka itina CON Matigari maku ni maya: matigari: %{available_balance} %{token_symbol} ushuru: %{tax} %{token_symbol} 0. coka thutha CON Masazogo ni gatuwirago: Masazo: %{available_balance} %{token_symbol} Ushuuru: %{tax} %{token_symbol} 0. Uya nyuma CON Dong mari en: Dong: %{available_balance} %{token_symbol} osuru: %{tax} %{token_symbol} 0. Dog chien CON Balansi kake akan salio: %{available_balance} %{token_symbol} ushuru: %{tax} %{token_symbol} 0. Dheebi
68 account_balances.with_rewards CON Your balances are as follows: balance: %{available_balance} %{token_symbol} fees: %{tax} %{token_symbol} rewards: %{bonus} %{token_symbol} 0. Back CON Salio zako ni zifuatazo: salio: %{available_balance} %{token_symbol} ushuru: %{tax} %{token_symbol} tuzo: %{bonus} %{token_symbol} 0. Rudi CON Utyalo waku ni uu: Utyalo: %{available_balance} %{token_symbol} Tax/ushuru: %{tax} %{token_symbol} muthinzio: %{bonus} %{token_symbol} 0. Syoka itina CON Salio zako ni zifuatazo: salio: %{available_balance} %{token_symbol} ushuru: %{tax} %{token_symbol} tuzo: %{bonus} %{token_symbol} 0. coka thutha CON Sazoro ni rituwiraro: Sazo: %{available_balance} %{token_symbol} Ushuuru: %{tax} %{token_symbol} Zawadi: %{bonus} %{token_symbol} 0. Uya Nyuma CON Dong mari en: Dong: %{available_balance} %{token_symbol} osuru: %{tax} %{token_symbol} mich: %{bonus} %{token_symbol} 0. Dog chien CON Balansi kake akan salio: %{available_balance} %{token_symbol} ushuru: %{tax} %{token_symbol} tuzo: %{bonus} %{token_symbol} 0. Dheebi
69 first_transaction_set CON %{first_transaction_set} 0. Back 11. Next 00. Exit CON %{first_transaction_set} 0. Rudi 11. Mbele 00. Ondoka CON %{first_transaction_set} 1. Mbee 00. Ondoka CON %{first_transaction_set} 1. Mbere 00. uma CON %{first_transaction_set} 1. Mbere 00. Uka CON %{first_transaction_set} 1. Nyime 00. Wuogi CON %{first_transaction_set} 1. Dhuur 00. Bai
70 middle_transaction_set CON %{middle_transaction_set} 11. Next 22. Previous 00. Exit CON %{middle_transaction_set} 11. Mbele 22. Rudi 00. Ondoka CON %{middle_transaction_set} 1. Mbee 2. Itina 00. Ondoka CON %{middle_transaction_set} 1. Mbere 2. coka thutha 00. Uma CON %{middle_transaction_set} 1. Mbere 2. Uya nyuma 00. Uka CON %{middle_transaction_set} 1. Nyime 2. Dog chien 00. Wuogi CON %{middle_transaction_set} 1. Dhuur 2. Dheebi 00. Bai
71 last_transaction_set CON %{last_transaction_set} 22. Previous 00. Exit CON %{last_transaction_set} 22. Rudi 00. Ondoka CON %{last_transaction_set} 2. Itina 00. Ondoka CON %{last_transaction_set} 2. Coka thutha 00. Uma CON %{last_transaction_set} 2. Uya Nyuma 00. Uka CON %{last_transaction_set} 2. Dog chien 00. Wuogi CON %{last_transaction_set} 2. Dhuur 00. Bai
72 exit END Thank you for using the service. END Asante kwa kutumia huduma. END Ni muvea kwa kutumia huduma ii. END Thegio ni kuhuthira mutabo END. Namvera kwa mahumizi ga ii huduma. END Erokamano kuom tiyo kodwa. END Asante kwa kutumia huduma.
73 exit_invalid_request END Invalid request. END Chaguo si sahihi. END Usakuo waku uyaile. END shaguro riaku ti riega END. Tsagulo karisawa sawa END Yiero okni kare END Ka at chaquad suninit
74 exit_invalid_menu_option CON Invalid menu option. For help,call %{support_phone}. 00. Back 99. Exit CON Chaguo lako sio sahihi. Kwa usaidizi piga simu %{support_phone} 00. Rudi 99. Ondoka CON Usakuo waku uyaile. Kwa utethyo kuna simu %{support_phone} 00. Itina 99. Ondoka CON Shaguro riaku ti riega.Kwa uteithio hura %{support_phone} 00. Coka thutha 99. Uma CON Tsaguloro karisawa sawa. Kuavizwa piga %{support_phone} 00. Uya Nyuma 99. Uka CON Yiero ni oknikare. Kuom kony go simu e %{support_phone} 00. Dog chien 99. Wuogi CON Ka at chaqui suninit.qarqarsa simu dai%{support_phone} 00. Dheebi 99. Bai
75 exit_invalid_input CON Invalid input. Nothing selected 00. Back 99. Exit CON Chaguo lako halipatikani. Hakuna kilichochaguliwa. 00. Rudi 99. Ondoka CON Usakuo waku wikwonekana.Vaii kindu kisakue. 00. Itina 99. Ondoka CON Shaguro riaku ritironekana. Hatiri kindu washaghura. 00. Coka thutha 99. Uma CON Tsaguloro karipatikana. Kakuna Kutsagurire chochosi. 00. Uya nyuma 99. Uka CON Yiero ni okyudre. Onge gima iyiero. 00. Dog chien 99. Wuogi CON Ka at chaguad injirt. oo 00. dheebi 99. Bai
76 exit_pin_blocked END Your PIN has been blocked. For help, please call %{support_phone}. END PIN yako imefungwa. Kwa usaidizi tafadhali piga simu %{support_phone}. END PIN yaku niyavingwa. Kutethwa kuna simu ino %{support_phone}. END PIN yaku niyahingwo. Kwa uteithio hura thimu %{support_phone}. END. Namba fitse yakwako ifungwa. Kwa kuavizwa unaangwa upige simu %{support_phone}. END Nambani mopondo olor. Kuom kony go simu e %{support_phone}. END Pin kake yahidat. Qarqarsa simu dai %{support_phone}.
77 exit_invalid_pin END The PIN you have entered is invalid. PIN must consist of 4 digits. For help, call %{support_phone}. END PIN uliyobonyeza sio sahihi. PIN lazima iwe na nambari nne. Kwa usaidizi piga simu %{support_phone}. END PIN ila wekia iyaile. Ni lasima PIN ithiwe na namba inya. Kutethwa kuna namba ii %{support_phone}. END PIN iria wekera tii njega. PIN nomoka ikorwo na namba inya. Kwa uteithio hura thimu %{support_phone}. END Namba fitse urohofya seyo, kaisawa. Namba fitswe inamalwa ikale na namba nee. Kwa kuvizwa, piga simu%{support_phone}. END. Namba mopondo miketo oknikare. Nyaka obed gi nembni ang'wen. Kuom kony go simu e %{support_phone}. END PIN ka at keket suninit. PIN Pin namba afuuri tatatu. Qarqarsa simu dai %{support_phone}.
78 exit_invalid_new_pin END The PIN you have entered is invalid. PIN must be different from your current PIN. For help, call %{support_phone}. END PIN uliyobonyeza sio sahihi. PIN lazima iwe tofauti na pin yako ya sasa. Kwa usaidizi piga simu %{support_phone}. END PIN ila wekia iyaile. PIN ni lasima ithiwe tofauti na pin yaku ya oyu. Kutethwa kuna namba ii %{support_phone}. END PIN uria wekera ti njega. PIN nomohaka ikorwo na namba ndiganu na ya riu . Kwa uteithio hora thimu %{support_phone}. END Namba fitswe uriohopya siyo ya karakara. Namba fitswe inahenzekana ikale itofauti na uhumirayo vivi. Kwa maavizo piga simu %{support_phone}. END Namba mopondo miketo oknikare. Nyaka obed mopogore gi nambani mopondo masani. Kuom kony gochi e %{support_phone}. END PIN ka at keket suninit.Pin kake walinfakaatin.Qarqars simu dai %{support_phone}.
79 exit_pin_mismatch END The new PIN does not match the one you entered. Please try again. For help, call %{support_phone}. END PIN mpya na udhibitisho wa pin mpya hazilingani. Tafadhali jaribu tena. Kwa usaidizi piga simu %{support_phone}. END PIN yumbya na uhakikisho wa pin yumbya syivwanene. Tafadhali tata ingi. Kutethwa kuna simu %{support_phone}. END PIN njeru na pin ya guetekeria shitira hianana . Geria ringi. Kwa uteithio hora thimu %{support_phone}. END Namba fitse uzdoinjiza kaikara kara na uriyohopya laphiri. Unavoywa ujeze kaheri. Kwa kuavizwa piga simu %{support_phone}. GIKO. Namba mopondo miketo opogore gi manikuongo keto. Kiyie to ket kendo. Kuom kony gochi e %{support_phone}. END PIN mpya na udhibitisho wa pin mpya hazilingani. Pin hareti ka at kekeet walinfakan. it dheebi amaale.Qarqars simu dai%{support_phone}.
80 exit_invalid_recipient CON Recipient's phone number is not registered or is invalid: 00. Retry 99. Exit CON Mpokeaji wa nambari hapatikani au sio sahihi. 00. Jaribu tena 99. Ondoka CON Mukwati wa namba ndokwatikana kana ii namba iyaile kana ti sahihi. 00. Tata ingi 99. Ondoka CON Mpokeaji wa nambari hapatikani au sio sahihi.Namba ya mutumirwo ndiranyitikana kana ti njega 00. Geria ringi 99. Uma CON Muphokezi wa namba kapatikana ama namba kai karakara. 00. Jeza Kaheri 99. Uka CON Jayuto mar nambani okyudre kata oknikare. 00. Tem kendo 99. Wuogi CON Mpokeaji wa nambari hapatikani au sio sahihi. 00. 99. Ondoka
81 exit_successful_transaction CON Your request has been sent. %{recipient_information} will receive %{transaction_amount} %{token_symbol} from %{sender_information}. 00. Back 99. Exit CON Ombi lako limetumwa. %{recipient_information} atapokea %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}. 00. Rudi 99. Ondoka CON Woni waku niwatumwa. %{recipient_information} nukupokea %{transaction_amount} %{token_symbol} kuma kwa %{sender_information}. 00. Itina 99. Ondoka CON Mahoya maku nimatomwo. %{recipient_information} akuamukira%{transaction_amount} %{token_symbol} kuma kwa %{sender_information}. 00. Coka 99. Uma CON Mavoyogo gahumwa. %{recipient_information} undaphokera %{transaction_amount} %{token_symbol} kuombola kwa %{sender_information}. 00. Uya Nyuma 99. Uka CON Kwayo ni oseor. %{recipient_information} oboyudo %{transaction_amount} %{token_symbol} kowuok kuom %{sender_information}. 00. Dog chien 99. Wuogi CON Qarqar kake yaergad. %{recipient_information} inargat %{transaction_amount} %{token_symbol} kutoka kwa %{sender_information}. 00. Dheebi 99. Bai
82 exit_insufficient_balance CON Payment of %{amount} %{token_symbol} to %{recipient_information} has failed due to insufficient balance. Your Sarafu-Network balances is: %{token_balance} 00. Back 99. Exit CON Malipo ya %{amount} %{token_symbol} kwa %{recipient_information} halijakamilika kwa sababu salio lako haitoshi. Akaunti yako ya Sarafu ina salio ifuatayo: %{token_balance} 00. Rudi 99. Ondoka CON Ndivi ya %{amount} %{token_symbol} kwa %{recipient_information} inavitukithwa nundu utyalyo waku ni munini. Kinandu chaku cha Sarafu kina utyalo uu: %{token_balance} 00. Itina 99. Ondoka CON Marehi ma %{amount} %{token_symbol} kwa %{recipient_information} matinarekereka tondu matigari maku matiraigana. Akaunti yako ya Sarafu ina salio ifuatayo: %{token_balance} 00. Coka 99. Uma CON Maripho ga %{amount} %{token_symbol} kwa %{recipient_information} Karidzangwe kukamirika Kwaukala sazoro Karitosha. Akauntiyo vivi ina sazo dza rituwiranavyo: %{token_balance} 00. Uya nyuma 99. Uka CON Chudo mar %{amount} %{token_symbol} kuom %{recipient_information} okotieki nikech dong ni okrom. Akaont ni mar Sarafu ni gi dong mar: %{token_balance} 00. Dog chien 99. Wuogi CON Malipo ka%{amount} %{token_symbol} kwa %{recipient_information} Inkamilikee balansi kake ingau Akaunti kake balansi akan kabd: %{token_balance} 00. Dheebi 99. Bai
83 exit_successful_token_selection CON Success! %{token_symbol} is your active Sarafu. 00. Back 99. Exit CON Chaguo lako limekamilika, %{token_symbol} ni sarafu itakayotumika. 00. Rudi 99. Ondoka
84 invalid_service_code Please dial %{valid_service_code} to access Sarafu Network Bonyeza %{valid_service_code} kutumia mtandao wa Sarafu Vinyia %{valid_service_code} kutumia mutandao wa Sarafu Hihinya%{valid_service_code} kuhudhira mutabo wa Sarafu Hofya %{valid_service_code} Kuhumira Mutandao wa sarafu Dii %{valid_service_code} mondo iti gi Sarafu Bonyeza %{valid_service_code} kutumia mtandao wa Sarafu
85 help CON For assistance call %{support_phone} 00. Back 99. Exit CON Kwa usaidizi piga simu %{support_phone} 0. Rudi 9. Ondoka CON Kwa utethyo kuna simu %{support_phone} 0. Itina 9. Ondoka CON Kwa uteithio hora thimu %{support_phone} 0. Coka 9. Uma CON Kwa Kuavizwa piga simu %{support_phone} 0. Uya nyuma 9. Uka CON Kuom kony go simu e %{support_phone} 0. Dog chien 9. Wuogi CON Qarqars simu dai%{support_phone} 0. Dheebi 9. Bai
86 complete CON Your request has been sent. You will receive an SMS shortly. 00. Back 99. Exit CON Ombi lako limetumwa. Utapokea uthibitishaji wa SMS kwa muda mfupi. 00. Rudi 99. Ondoka CON Woni waku niwatumwa. Nukwata SMS ya kwonya ivinda ite yasa. 00. Itina 99. Ondoka CON Mahoya maku nimatomwo. Niukuamukira SMS ya guitikirika ihinda ikuhi . 00. Coka 99. Uma CON Vyoyoro rihumwa. Undaphokera Uthibitishaji wa SMS kwa muda mufuhi. 00. Uya nyuma 99. Uka CON Kwayo ni oseor. Iboyudo mesej mar ote ni bang' saa matin. 00. Dog chien 99. Wuogi CON Qarqars kake yaergad. Utapokea uthibitishaji wa SMS kwa muda mfupi. 00. Dheebi 99. Bai
87 account_creation_prompt END Your account is being created. You will receive an SMS when your account is ready. END Akaunti yako ya Sarafu inatayarishwa. Utapokea ujumbe wa SMS akaunti yako ikiwa tayari. END Akaunti yako ya Sarafu yendeye usovwa. Nukwata SMS akaunti yaku yasovwa. END Akaunti yaku ya Sarafu niiraharirio.Niugutumirwo SMS akauti yaku ya rikio kuharirio END Akauntiyo ya sarafu idzikoni. Undaphokera ujumbe wa SMS ichikala tayari. END Akaont ni mar Sarafu iloso. Iboyudo mesej ka akaont ni otieki. END Akaunti yako ya Sarafu inatayarishwa. Utapokea ujumbe wa SMS akaunti yako ikiwa tayari.
88 initial_middle_language_set CON Choose language: %{middle_language_set} 11. Next 22. Previous 00. Exit CON Chagua lugha: %{middle_language_set} 11. Mbele 22. Rudi 00. Ondoka
89 initial_last_language_set CON Choose language: %{last_language_set} 22. Previous 00. Exit CON Choose language: %{last_language_set} 22. Rudi 00. Ondoka
90 middle_language_set CON Choose language: %{middle_language_set} 11. Next 22. Previous 00. Exit CON Chagua lugha: %{middle_language_set} 11. Mbele 22. Rudi 00. Ondoka
91 last_language_set CON Choose language: %{last_language_set} 22. Previous 00. Exit CON Choose language: %{last_language_set} 22. Rudi 00. Ondoka