Skip to content

Commit 715426e

Browse files
committed
docs: readme
1 parent 12516af commit 715426e

File tree

2 files changed

+221
-4
lines changed

2 files changed

+221
-4
lines changed

README-summary.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,19 @@ If you like using this library, please consider [supporting the development ❤
3838
- [pauseFor()](https://github.com/Sv443-Network/UserUtils#pausefor) - pause the execution of a function for a given amount of time
3939
- [debounce()](https://github.com/Sv443-Network/UserUtils#debounce) - call a function only once, after a given amount of time
4040
- [fetchAdvanced()](https://github.com/Sv443-Network/UserUtils#fetchadvanced) - wrapper around the fetch API with a timeout option
41+
- [insertValues()](https://github.com/Sv443-Network/UserUtils#insertvalues) - insert values into a string at specified placeholders
4142
- Arrays:
4243
- [randomItem()](https://github.com/Sv443-Network/UserUtils#randomitem) - returns a random item from an array
4344
- [randomItemIndex()](https://github.com/Sv443-Network/UserUtils#randomitemindex) - returns a tuple of a random item and its index from an array
4445
- [takeRandomItem()](https://github.com/Sv443-Network/UserUtils#takerandomitem) - returns a random item from an array and mutates it to remove the item
4546
- [randomizeArray()](https://github.com/Sv443-Network/UserUtils#randomizearray) - returns a copy of the array with its items in a random order
47+
- Translation:
48+
- [tr()](https://github.com/Sv443-Network/UserUtils#tr) - simple translation of a string to another language
49+
- [tr.addLanguage()](https://github.com/Sv443-Network/UserUtils#traddlanguage) - add a language and its translations
50+
- [tr.setLanguage()](https://github.com/Sv443-Network/UserUtils#trsetlanguage) - set the currently active language
51+
- [tr.getLanguage()](https://github.com/Sv443-Network/UserUtils#trgetlanguage) - returns the currently active language
52+
- Utility types for TypeScript
53+
- [Stringifiable](https://github.com/Sv443-Network/UserUtils#stringifiable) - any value that is a string or can be converted to one (implicitly or explicitly)
4654

4755
<br><br>
4856

README.md

Lines changed: 213 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ If you like using this library, please consider [supporting the development ❤
1414
- [**Preamble**](#preamble)
1515
- [**License**](#license)
1616
- [**Features**](#features)
17-
- [DOM:](#dom)
17+
- [**DOM:**](#dom)
1818
- [onSelector()](#onselector) - call a listener once a selector is found in the DOM
1919
- [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()`
2020
- [getSelectorMap()](#getselectormap) - returns all currently registered selectors, listeners and options
@@ -28,21 +28,29 @@ If you like using this library, please consider [supporting the development ❤
2828
- [interceptWindowEvent()](#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
2929
- [amplifyMedia()](#amplifymedia) - amplify an audio or video element's volume past the maximum of 100%
3030
- [isScrollable()](#isscrollable) - check if an element has a horizontal or vertical scroll bar
31-
- [Math:](#math)
31+
- [**Math:**](#math)
3232
- [clamp()](#clamp) - constrain a number between a min and max value
3333
- [mapRange()](#maprange) - map a number from one range to the same spot in another range
3434
- [randRange()](#randrange) - generate a random number between a min and max boundary
35-
- [Misc:](#misc)
35+
- [**Misc:**](#misc)
3636
- [ConfigManager()](#configmanager) - class that manages persistent userscript configurations, including data migration
3737
- [autoPlural()](#autoplural) - automatically pluralize a string
3838
- [pauseFor()](#pausefor) - pause the execution of a function for a given amount of time
3939
- [debounce()](#debounce) - call a function only once, after a given amount of time
4040
- [fetchAdvanced()](#fetchadvanced) - wrapper around the fetch API with a timeout option
41-
- [Arrays:](#arrays)
41+
- [insertValues()](#insertvalues) - insert values into a string at specified placeholders
42+
- [**Arrays:**](#arrays)
4243
- [randomItem()](#randomitem) - returns a random item from an array
4344
- [randomItemIndex()](#randomitemindex) - returns a tuple of a random item and its index from an array
4445
- [takeRandomItem()](#takerandomitem) - returns a random item from an array and mutates it to remove the item
4546
- [randomizeArray()](#randomizearray) - returns a copy of the array with its items in a random order
47+
- [**Translation:**](#translation)
48+
- [tr()](#tr) - simple translation of a string to another language
49+
- [tr.addLanguage()](#traddlanguage) - add a language and its translations
50+
- [tr.setLanguage()](#trsetlanguage) - set the currently active language for translations
51+
- [tr.getLanguage()](#trgetlanguage) - returns the currently active language
52+
- [**Utility types for TypeScript:**](#utility-types)
53+
- [Stringifiable](#stringifiable) - any value that is a string or can be converted to one (implicitly or explicitly)
4654

4755
<br><br>
4856

@@ -968,8 +976,209 @@ console.log(foo); // [1, 2, 3, 4, 5, 6] - original array is not mutated
968976
969977
</details>
970978
979+
<br><br>
980+
981+
## Translation:
982+
This is a very lightweight translation function that can be used to translate simple strings.
983+
Pluralization is not supported but can be achieved manually by adding variations to the translations, identified by a different suffix. See the example section of [`tr.addLanguage()`](#traddlanguage) for an example on how this might be done.
984+
985+
<br>
986+
987+
### tr()
988+
Usage:
989+
```ts
990+
tr(key: string, ...values: Stringifiable[]): string
991+
```
992+
993+
The function returns the translation of the passed key in the language added by [`tr.addLanguage()`](#traddlanguage) and set by [`tr.setLanguage()`](#trsetlanguage)
994+
Should the translation contain placeholders in the format `%n`, where `n` is the number of the value starting at 1, they will be replaced with the respective item of the `values` rest parameter.
995+
996+
If the key is not found or no language has been added or set before calling this function, it will return the key itself.
997+
If the key is found and the translation contains placeholders but no values are passed, it will return the translation as-is, including unmodified placeholders.
998+
If the key is found, the translation doesn't contain placeholders but values are still passed, they will be ignored and the translation will be returned as-is.
999+
1000+
<details><summary><h4>Example - click to view</h4></summary>
1001+
1002+
```ts
1003+
import { tr } from "@sv443-network/userutils";
1004+
1005+
tr.addLanguage("en", {
1006+
"welcome": "Welcome",
1007+
"welcome_name": "Welcome, %1",
1008+
});
1009+
tr.addLanguage("de", {
1010+
"welcome": "Willkommen",
1011+
"welcome_name": "Willkommen, %1",
1012+
});
1013+
1014+
// this has to be called at least once before calling tr()
1015+
tr.setLanguage("en");
1016+
1017+
console.log(tr("welcome")); // "Welcome"
1018+
console.log(tr("welcome_name", "John")); // "Welcome, John"
1019+
console.log(tr("non_existent_key")); // "non_existent_key"
1020+
1021+
// language can be changed at any time, synchronously
1022+
tr.setLanguage("de");
1023+
1024+
console.log(tr("welcome")); // "Willkommen"
1025+
console.log(tr("welcome_name", "John")); // "Willkommen, John"
1026+
```
1027+
1028+
</details>
1029+
9711030
<br>
9721031
1032+
### tr.addLanguage()
1033+
Usage:
1034+
```ts
1035+
tr.addLanguage(language: string, translations: Record<string, string>): void
1036+
```
1037+
1038+
Adds a language and its associated translations to the translation function.
1039+
The passed language can be any unique identifier, though I recommend sticking to the [ISO 639-1 standard.](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
1040+
The passed translations should be an object where the key is the translation key used in `tr()` and the value is the translation itself.
1041+
If `tr.addLanguage()` is called multiple times with the same language, the previous translations of that language will be overwritten.
1042+
1043+
The translation values may contain placeholders in the format `%n`, where `n` is the number of the value starting at 1.
1044+
These can be used to inject values into the translation when calling `tr()`
1045+
1046+
<details><summary><h4>Example - click to view</h4></summary>
1047+
1048+
```ts
1049+
import { tr } from "@sv443-network/userutils";
1050+
1051+
// add a language with associated translations:
1052+
1053+
tr.addLanguage("de", {
1054+
"color": "Farbe",
1055+
});
1056+
1057+
1058+
// with placeholders:
1059+
1060+
tr.addLanguage("en", {
1061+
"welcome_generic": "Welcome!",
1062+
"welcome_name": "Welcome, %1!",
1063+
"welcome_extended": "Welcome, %1!\nYour last login was on %2\nYou have %3 unread messages",
1064+
});
1065+
1066+
1067+
// can work for multiple locales too:
1068+
1069+
tr.addLanguage("en-US", {
1070+
"fries": "french fries",
1071+
});
1072+
tr.addLanguage("en-GB", {
1073+
"fries": "chips",
1074+
});
1075+
1076+
1077+
// apply default values for different locales to reduce redundancy:
1078+
1079+
const translation_de = {
1080+
"greeting": "Guten Tag!",
1081+
"foo": "Foo",
1082+
};
1083+
tr.addLanguage("de-DE", translation_de);
1084+
tr.addLanguage("de-CH", {
1085+
...translation_de,
1086+
// overwrite the "greeting" but keep other keys as they are
1087+
"greeting": "Grüezi!",
1088+
});
1089+
tr.addLanguage("de-AT", {
1090+
...translation_de,
1091+
// overwrite "greeting" again but keep other keys as they are
1092+
"greeting": "Grüß Gott!",
1093+
});
1094+
1095+
1096+
// example for custom pluralization:
1097+
1098+
tr.addLanguage("en", {
1099+
"items_added-1": "Added 1 item to your cart",
1100+
"items_added-n": "Added %1 items to your cart",
1101+
});
1102+
1103+
/** Returns the custom pluralization identifier */
1104+
function pl(num: number | unknown[] | NodeList) {
1105+
if(Array.isArray(num))
1106+
num = num.length;
1107+
return num === 1 ? "1" : "n";
1108+
};
1109+
1110+
const items = ["foo"];
1111+
tr(`items_added-${pl(items)}`, items.length); // "Added 1 item to your cart"
1112+
1113+
items.push("bar");
1114+
tr(`items_added-${pl(items)}`, items.length); // "Added 2 items to your cart"
1115+
```
1116+
1117+
</details>
1118+
1119+
<br>
1120+
1121+
### tr.setLanguage()
1122+
Usage:
1123+
```ts
1124+
tr.setLanguage(language: string): void
1125+
```
1126+
1127+
Synchronously sets the language that will be used for translations.
1128+
No validation is done on the passed language, so make sure it is correct and it has been added with `tr.addLanguage()` before calling `tr()`
1129+
1130+
For an example, see [`tr()`](#tr)
1131+
1132+
<br>
1133+
1134+
### tr.getLanguage()
1135+
Usage:
1136+
```ts
1137+
tr.getLanguage(): string | undefined
1138+
```
1139+
1140+
Returns the currently active language set by [`tr.setLanguage()`](#trsetlanguage)
1141+
If no language has been set yet, it will return undefined.
1142+
1143+
<br><br>
1144+
1145+
## Utility types:
1146+
UserUtils also offers some utility types that can be used in TypeScript projects.
1147+
They don't alter the runtime behavior of the code, but they can be used to make the code more readable and to prevent errors.
1148+
1149+
### Stringifiable
1150+
This type describes any value that either is a string itself or can be converted to a string.
1151+
To be considered stringifiable, the object needs to have a `toString()` method that returns a string (all primitive types have this method).
1152+
This method allows not just explicit conversion by calling it, but also implicit conversion by passing it into the `String()` constructor or by interpolating it in a template string.
1153+
1154+
<details><summary><h4>Example - click to view</h4></summary>
1155+
1156+
```ts
1157+
import type { Stringifiable } from "@sv443-network/userutils";
1158+
1159+
function logSomething(value: Stringifiable) {
1160+
console.log(`Log: ${value}`); // implicit conversion using `value.toString()`
1161+
}
1162+
1163+
const fooObject = {
1164+
toString: () => "hello world",
1165+
};
1166+
1167+
const barObject = {
1168+
baz: "",
1169+
};
1170+
1171+
logSomething("foo"); // "Log: foo"
1172+
logSomething(42); // "Log: 42"
1173+
logSomething(true); // "Log: true"
1174+
logSomething({}); // "Log: [object Object]"
1175+
logSomething(Symbol(1)); // "Log: Symbol(1)"
1176+
logSomething(fooObject); // "Log: hello world"
1177+
logSomething(barObject); // type error
1178+
```
1179+
1180+
</details>
1181+
9731182
<br><br><br><br>
9741183
9751184
<div style="text-align: center;" align="center">

0 commit comments

Comments
 (0)