localizationkit 3.0.1__tar.gz → 3.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {localizationkit-3.0.1 → localizationkit-3.1.0}/PKG-INFO +19 -1
  2. {localizationkit-3.0.1 → localizationkit-3.1.0}/README.md +18 -0
  3. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/localization_types.py +8 -0
  4. localizationkit-3.1.0/localizationkit/tests/token_adjacency.py +62 -0
  5. {localizationkit-3.0.1 → localizationkit-3.1.0}/pyproject.toml +3 -5
  6. {localizationkit-3.0.1 → localizationkit-3.1.0}/LICENSE +0 -0
  7. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/__init__.py +0 -0
  8. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/configuration.py +0 -0
  9. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/exceptions.py +0 -0
  10. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/__init__.py +0 -0
  11. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/comment_linebreaks.py +0 -0
  12. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/comment_similarity.py +0 -0
  13. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/duplicate_keys.py +0 -0
  14. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/has_comments.py +0 -0
  15. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/has_value.py +0 -0
  16. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/invalid_tokens.py +0 -0
  17. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/key_length.py +0 -0
  18. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/objectivec_alternative_tokens.py +0 -0
  19. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/placeholder_token_explanation.py +0 -0
  20. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/swift_interpolation.py +0 -0
  21. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/test_case.py +0 -0
  22. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/token_matching.py +0 -0
  23. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/tests/token_position_identifiers.py +0 -0
  24. {localizationkit-3.0.1 → localizationkit-3.1.0}/localizationkit/utility_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: localizationkit
3
- Version: 3.0.1
3
+ Version: 3.1.0
4
4
  Summary: String localization tests
5
5
  Home-page: https://github.com/Microsoft/localizationkit
6
6
  License: MIT
@@ -238,6 +238,24 @@ Opt-In: `true`
238
238
 
239
239
  Checks that strings do not contain Swift style interpolation values since these cannot be localized.
240
240
 
241
+ ## Token Adjacency
242
+
243
+ Identifier: `token_adjacency`
244
+ Opt-In: `true`
245
+
246
+ Checks that attempts for pluralization or other similar operations are not in place, e.g. `Open %@s in the app` doesn't translate well.
247
+
248
+ _Note: It is recommended that this is run on latin alphabet using languages only._
249
+
250
+ <details>
251
+ <summary>Configuration</summary>
252
+
253
+ | Parameter | Type | Acceptable Values | Default | Details |
254
+ | --- | --- | --- | --- | --- |
255
+ | `only_check_language` | str or `None` | Language code | `None` | Set to only check a particular language. **Recommended** |
256
+
257
+ </details>
258
+
241
259
  ## Token Matching
242
260
 
243
261
  Identifier: `token_matching`
@@ -211,6 +211,24 @@ Opt-In: `true`
211
211
 
212
212
  Checks that strings do not contain Swift style interpolation values since these cannot be localized.
213
213
 
214
+ ## Token Adjacency
215
+
216
+ Identifier: `token_adjacency`
217
+ Opt-In: `true`
218
+
219
+ Checks that attempts for pluralization or other similar operations are not in place, e.g. `Open %@s in the app` doesn't translate well.
220
+
221
+ _Note: It is recommended that this is run on latin alphabet using languages only._
222
+
223
+ <details>
224
+ <summary>Configuration</summary>
225
+
226
+ | Parameter | Type | Acceptable Values | Default | Details |
227
+ | --- | --- | --- | --- | --- |
228
+ | `only_check_language` | str or `None` | Language code | `None` | Set to only check a particular language. **Recommended** |
229
+
230
+ </details>
231
+
214
232
  ## Token Matching
215
233
 
216
234
  Identifier: `token_matching`
@@ -36,6 +36,14 @@ class LocalizedString:
36
36
  """
37
37
  return LocalizedString._TOKEN_PATTERN.findall(self.value)
38
38
 
39
+ def tokens_with_positions(self) -> list[tuple[str, int, int]]:
40
+ """Find and return the tokens in the string with their start and end position.
41
+
42
+ :returns: The list of tuples containing the token, start, and end for each.
43
+ """
44
+ tokens = LocalizedString._TOKEN_PATTERN.finditer(self.value)
45
+ return [(match.group(0), match.start(), match.end()) for match in tokens]
46
+
39
47
  def comment_tokens(self) -> list[str]:
40
48
  """Find and return the tokens in the comment string.
41
49
 
@@ -0,0 +1,62 @@
1
+ """Token matching."""
2
+
3
+ from typing import Any
4
+
5
+ from localizationkit.tests.test_case import LocalizationTestCase
6
+
7
+
8
+ class TokenAdjacency(LocalizationTestCase):
9
+ """Check that nothing is directly adjacent to a token. e.g. Don't allow `You have new %@s` for plurals."""
10
+
11
+ @classmethod
12
+ def name(cls) -> str:
13
+ return "token_adjacency"
14
+
15
+ @classmethod
16
+ def is_opt_in(cls) -> bool:
17
+ """Check if the test is opt in or not."""
18
+ return True
19
+
20
+ @classmethod
21
+ def default_settings(cls) -> dict[str, Any]:
22
+ return {"only_check_language": None}
23
+
24
+ def run_test(self) -> list[tuple[str, str]]:
25
+
26
+ violations = []
27
+
28
+ only_check_language = self.get_setting("only_check_language")
29
+
30
+ allowed_characters = '.\n\r\t,:;" '
31
+
32
+ for string in self.collection.localized_strings:
33
+ if only_check_language and string.language_code != only_check_language:
34
+ continue
35
+
36
+ tokens = string.tokens_with_positions()
37
+
38
+ if not tokens or len(tokens) == 0:
39
+ continue
40
+
41
+ for token, start, end in tokens:
42
+ preceding_char = string.value[start - 1] if start > 0 else None
43
+ if preceding_char:
44
+ if preceding_char not in allowed_characters:
45
+ violations.append(
46
+ (
47
+ f"Token '{token}' is directly preceded by '{preceding_char}' in string: {string}",
48
+ string.language_code,
49
+ )
50
+ )
51
+
52
+ succeeding_char = string.value[end] if end < len(string.value) else None
53
+ if succeeding_char:
54
+ if succeeding_char not in allowed_characters:
55
+ violations.append(
56
+ (
57
+ f"Token '{token}' is directly followed by '{succeeding_char}' in string: {string}",
58
+ string.language_code,
59
+ )
60
+ )
61
+
62
+ return violations
@@ -1,13 +1,11 @@
1
1
  [tool.poetry]
2
2
  name = "localizationkit"
3
- version = "3.0.1"
3
+ version = "3.1.0"
4
4
  description = "String localization tests"
5
5
 
6
6
  license = "MIT"
7
7
 
8
- authors = [
9
- "Dale Myers <dalemy@microsoft.com>"
10
- ]
8
+ authors = ["Dale Myers <dalemy@microsoft.com>"]
11
9
 
12
10
  readme = 'README.md'
13
11
 
@@ -26,7 +24,7 @@ classifiers = [
26
24
  'Programming Language :: Python :: 3.11',
27
25
  'Topic :: Software Development',
28
26
  'Topic :: Software Development :: Testing',
29
- 'Topic :: Utilities'
27
+ 'Topic :: Utilities',
30
28
  ]
31
29
 
32
30
  [tool.poetry.dependencies]
File without changes