imba-localization 0.2.8 → 0.3.1
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.
- package/README.md +60 -24
- package/localization.imba +51 -1
- package/package.json +3 -12
- package/components.imba +0 -51
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ A lightweight Imba module for loading and handling JSON-based localization files
|
|
|
11
11
|
- 🧠 **Intuitive access** - Proxy-based access to translation strings
|
|
12
12
|
- 📡 **Event handling** - Support for `onready`, `onchange`, and `onerror` events
|
|
13
13
|
- 🚀 **Simple integration** - Easy to use in any Imba-based web application
|
|
14
|
-
- 🧩 **`<
|
|
14
|
+
- 🧩 **`<language-selector>`** - Plug and play tag component for switching languages
|
|
15
15
|
|
|
16
16
|
## 📘 Notes
|
|
17
17
|
|
|
@@ -54,10 +54,10 @@ Add this to your HTML head to load the localization file simultaneously with you
|
|
|
54
54
|
|
|
55
55
|
```imba
|
|
56
56
|
# app.imba
|
|
57
|
-
import {
|
|
57
|
+
import { Localization } from 'imba-localization'
|
|
58
58
|
|
|
59
59
|
# Create an instance with the JSON URL and optional default language
|
|
60
|
-
const loc = new
|
|
60
|
+
const loc = new Localization("path/to/lang.json", "en")
|
|
61
61
|
|
|
62
62
|
# Set up event handlers
|
|
63
63
|
loc.onready = do
|
|
@@ -69,7 +69,7 @@ loc.onready = do
|
|
|
69
69
|
console.log loc['user']['profile'] # Accessing nested properties
|
|
70
70
|
|
|
71
71
|
loc.onerror = do(error, details)
|
|
72
|
-
# The
|
|
72
|
+
# The Localization object can return following types of errors:
|
|
73
73
|
# 'no_localization_file' - if there were a problem when downloading JSON file
|
|
74
74
|
# 'no_default_localization' - if there is no localization in the file for the default language
|
|
75
75
|
# 'no_localization_key' - if there is no requiered (from the interface) key in the file
|
|
@@ -123,7 +123,7 @@ Your localization file should follow this format:
|
|
|
123
123
|
### Constructor
|
|
124
124
|
|
|
125
125
|
```imba
|
|
126
|
-
new
|
|
126
|
+
new Localization(url, default = 'en')
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
- `url`: Path to your JSON localization file
|
|
@@ -148,13 +148,15 @@ new LocalizationState(url, default = 'en')
|
|
|
148
148
|
A customizable dropdown component that allows users to select from available in the JSON localization file languages.
|
|
149
149
|
|
|
150
150
|
```imba
|
|
151
|
-
import {
|
|
152
|
-
const loc = new
|
|
151
|
+
import { Localization } from 'imba-localization'
|
|
152
|
+
const loc = new Localization("path/to/lang.json", "en")
|
|
153
153
|
|
|
154
|
-
#
|
|
154
|
+
# after importing Localization object
|
|
155
|
+
# <language-selector> tag will be available
|
|
156
|
+
# in any of you project your UI component
|
|
155
157
|
tag AppHeader
|
|
156
158
|
<self>
|
|
157
|
-
<
|
|
159
|
+
<language-selector state=loc> # state attribute is mandatory
|
|
158
160
|
```
|
|
159
161
|
|
|
160
162
|
To make this component work as intended, your JSON file will need some adjustments. For each supported language you will need to define the display name for the language and also the country code for the flag to show (for example `en` language is used in `gb` and `us` countries):
|
|
@@ -189,8 +191,11 @@ css
|
|
|
189
191
|
.main-arrow
|
|
190
192
|
w:16px h:16px ml:auto
|
|
191
193
|
fill:light-dark(#000000,#FFFFFF)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
+
transition: transform $ease ease
|
|
195
|
+
.main-arrow-passive
|
|
196
|
+
scale-y:-1
|
|
197
|
+
.main-arrow-active
|
|
198
|
+
scale-y:1
|
|
194
199
|
.menu
|
|
195
200
|
t:100% l:50% x:-50% mt:2px rd:8px rd:8px py:5px zi:999
|
|
196
201
|
fw:500 fs:13px
|
|
@@ -206,14 +211,19 @@ css
|
|
|
206
211
|
.menu-item-text
|
|
207
212
|
fs:13px
|
|
208
213
|
```
|
|
209
|
-
|
|
214
|
+
`<language-selector>` can be easily customized through CSS and Imba tag (class) inheritance. Here how the above classes can be adjusted via the inheritance, or through CSS selectors:
|
|
210
215
|
|
|
211
216
|
```imba
|
|
212
|
-
|
|
213
|
-
|
|
217
|
+
|
|
218
|
+
import { Localization } from 'imba-localization'
|
|
219
|
+
const loc = new Localization("path/to/lang.json", "en")
|
|
220
|
+
|
|
221
|
+
# --------------------
|
|
222
|
+
# Inheritance
|
|
223
|
+
# --------------------
|
|
214
224
|
|
|
215
225
|
# Create an inheritent class
|
|
216
|
-
tag
|
|
226
|
+
tag custom-languages < language-selector
|
|
217
227
|
css
|
|
218
228
|
$ease: 1s
|
|
219
229
|
.menu-item rd:2px
|
|
@@ -222,7 +232,34 @@ tag Languages < LocalizationSelector
|
|
|
222
232
|
# Using the adjusted component
|
|
223
233
|
tag MyApp
|
|
224
234
|
<self>
|
|
225
|
-
<
|
|
235
|
+
<custom-languages state=loc>
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# --------------------
|
|
239
|
+
# CSS selectors
|
|
240
|
+
# --------------------
|
|
241
|
+
|
|
242
|
+
global css
|
|
243
|
+
language-selector
|
|
244
|
+
@not(#_) # is needed for higher precedence
|
|
245
|
+
.main
|
|
246
|
+
bgc: #992033
|
|
247
|
+
bd: 1px solid #992033
|
|
248
|
+
.main-active
|
|
249
|
+
bgc: blue2
|
|
250
|
+
bd: 1px solid #992033
|
|
251
|
+
.menu
|
|
252
|
+
bgc: #992033
|
|
253
|
+
bd: 1px solid #992033
|
|
254
|
+
.menu-item
|
|
255
|
+
bgc@hover: orange4
|
|
256
|
+
c@hover: black
|
|
257
|
+
|
|
258
|
+
# Using component that will be restyled
|
|
259
|
+
tag MyApp
|
|
260
|
+
<self>
|
|
261
|
+
<language-selector state=loc>
|
|
262
|
+
|
|
226
263
|
```
|
|
227
264
|
|
|
228
265
|
#### Flag collections
|
|
@@ -230,7 +267,7 @@ tag MyApp
|
|
|
230
267
|
You can redefine the collection of flag icons through the `icons` attribute:
|
|
231
268
|
|
|
232
269
|
```imba
|
|
233
|
-
<
|
|
270
|
+
<language-selector icons='https://flagicons.lipis.dev/flags/4x3/##.svg'>
|
|
234
271
|
```
|
|
235
272
|
There are many flag collections out there:
|
|
236
273
|
- https://kapowaz.github.io/square-flags/flags/##.svg (default one)
|
|
@@ -247,13 +284,12 @@ You can use any other collection you prefer, just change the actual country code
|
|
|
247
284
|
You can use any arrow icon you prefer (or remove it though CSS) by passing a tag of the image to the LanguageSelector `arrow` attribute:
|
|
248
285
|
|
|
249
286
|
```imba
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
<path d="...">
|
|
287
|
+
const arrow =
|
|
288
|
+
<svg viewBox="..." xmlns="http://www.w3.org/2000/svg">
|
|
289
|
+
<path d="...">
|
|
254
290
|
|
|
255
291
|
|
|
256
|
-
<
|
|
292
|
+
<language-selector arrow=arrow>
|
|
257
293
|
```
|
|
258
294
|
|
|
259
295
|
### ArrowIcon
|
|
@@ -261,10 +297,10 @@ tag SomeIcon
|
|
|
261
297
|
The default arrow icon used in the LocalizationSelector component is available as a separate icon (in case for some reason you don't want to use [imba-phosphor-icons](https://www.npmjs.com/package/imba-phosphor-icons) package by Sindre).
|
|
262
298
|
|
|
263
299
|
```imba
|
|
264
|
-
import {
|
|
300
|
+
import {svg-arrow-down} from 'imba-localization'
|
|
265
301
|
|
|
266
302
|
tag App
|
|
267
303
|
<self>
|
|
268
|
-
<
|
|
304
|
+
<{svg-arrow-down}>
|
|
269
305
|
css w:20px h:20px stroke:red
|
|
270
306
|
```
|
package/localization.imba
CHANGED
|
@@ -49,4 +49,54 @@ export class Localization
|
|
|
49
49
|
name = name and languages[name] ? name : active
|
|
50
50
|
if window.localStorage.getItem('imba-localization') != name
|
|
51
51
|
window.localStorage.setItem('imba-localization', name)
|
|
52
|
-
onchange(name) if onchange isa Function
|
|
52
|
+
onchange(name) if onchange isa Function
|
|
53
|
+
|
|
54
|
+
export const svg-arrow-down =
|
|
55
|
+
<svg viewBox="0 0 256 256">
|
|
56
|
+
<path d="M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z">
|
|
57
|
+
|
|
58
|
+
tag language-selector
|
|
59
|
+
state
|
|
60
|
+
icons = "https://kapowaz.github.io/square-flags/flags/##.svg"
|
|
61
|
+
#dropdown = false
|
|
62
|
+
arrow = svg-arrow-down
|
|
63
|
+
|
|
64
|
+
def onselect key
|
|
65
|
+
#dropdown = false
|
|
66
|
+
state.active = key
|
|
67
|
+
|
|
68
|
+
css
|
|
69
|
+
$ease: 0.5s
|
|
70
|
+
.main rd:8px px:15px py:8px cursor:pointer bgc:light-dark(#000000/10, #FFFFFF/20) fw:500 fs:13px ead:$ease
|
|
71
|
+
.main-active bgc:light-dark(#000000/20, #FFFFFF/30)
|
|
72
|
+
.main-flag mr:10px rd:50% w:20px h:20px
|
|
73
|
+
.main-name mr:10px
|
|
74
|
+
.main-arrow w:16px h:16px fill:light-dark(#000000,#FFFFFF) ml:auto transition: transform $ease ease
|
|
75
|
+
.main-arrow-passive scale-y:-1
|
|
76
|
+
.main-arrow-active scale-y:1
|
|
77
|
+
.menu t:100% l:50% x:-50% zi:999 backdrop-filter:blur(20px) mt:2px rd:8px rd:8px py:5px bgc:light-dark(#000000/5, #FFFFFF/10) fw:500 fs:13px ead:$ease
|
|
78
|
+
.menu-item d:hflex ai:center px:10px py:5px rd:8px cursor:pointer bg@hover:light-dark(#000000/10, #FFFFFF/20) m:5px
|
|
79
|
+
.menu-item-icon h:20px w:20px mr:10px rd:50%
|
|
80
|
+
.menu-item-text fs:13px
|
|
81
|
+
|
|
82
|
+
def icon country
|
|
83
|
+
return icons.replace('##',country)
|
|
84
|
+
|
|
85
|
+
def mouseleave e
|
|
86
|
+
const rect = self.getBoundingClientRect!
|
|
87
|
+
const menu = $menu.getBoundingClientRect!
|
|
88
|
+
const inside = e.clientY >= menu.bottom || e.clientY <= rect.top || (e.clientX <= rect.left and e.clientY <= rect.bottom) || (e.clientX <= menu.left and e.clientY >= menu.top) || (e.clientX >= rect.right and e.clientY <= rect.bottom) || (e.clientX >= menu.right and e.clientY >= menu.top)
|
|
89
|
+
#dropdown = !inside
|
|
90
|
+
|
|
91
|
+
<self [pos:rel] @mouseenter=(#dropdown = true) @mouseleave=mouseleave>
|
|
92
|
+
<div.main [pos:rel d:hcc] .main-active=#dropdown>
|
|
93
|
+
<img.main-flag src=icon(state[state.active].$.flag)>
|
|
94
|
+
<div.main-name> state.$.name
|
|
95
|
+
<{arrow}.main-arrow .main-arrow-passive=!#dropdown .main-arrow-active=#dropdown>
|
|
96
|
+
|
|
97
|
+
if #dropdown
|
|
98
|
+
<div$menu.menu [pos:abs w:100% > max-content o@off:0] ease>
|
|
99
|
+
for own key, value of state.languages
|
|
100
|
+
<div.menu-item @click=onselect(key) [d:none]=(key == state.active)>
|
|
101
|
+
<img.menu-item-icon src=icon(value.$.flag)>
|
|
102
|
+
<span.menu-item-text> value.$.name
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imba-localization",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/HeapVoid/imba-localization.git"
|
|
@@ -13,15 +13,6 @@
|
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"files": [
|
|
16
|
-
"localization.imba"
|
|
17
|
-
|
|
18
|
-
],
|
|
19
|
-
"exports": {
|
|
20
|
-
".": {
|
|
21
|
-
"import": "./localization.imba"
|
|
22
|
-
},
|
|
23
|
-
"./components": {
|
|
24
|
-
"import": "./components.imba"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
16
|
+
"localization.imba"
|
|
17
|
+
]
|
|
27
18
|
}
|
package/components.imba
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
const arrow-down =
|
|
2
|
-
<svg viewBox="0 0 256 256">
|
|
3
|
-
<path d="M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z">
|
|
4
|
-
|
|
5
|
-
tag icon-arrow-down
|
|
6
|
-
<self>
|
|
7
|
-
<{arrow-down}>
|
|
8
|
-
|
|
9
|
-
tag language-selector
|
|
10
|
-
state
|
|
11
|
-
icons = "https://kapowaz.github.io/square-flags/flags/##.svg"
|
|
12
|
-
#dropdown = false
|
|
13
|
-
icon-arrow = arrow-down
|
|
14
|
-
|
|
15
|
-
def onselect key
|
|
16
|
-
#dropdown = false
|
|
17
|
-
state.active = key
|
|
18
|
-
|
|
19
|
-
css
|
|
20
|
-
$ease: 0.5s
|
|
21
|
-
.main rd:8px px:15px py:8px cursor:pointer bgc:light-dark(#000000/10, #FFFFFF/20) fw:500 fs:13px ead:$ease
|
|
22
|
-
.main-active bgc:light-dark(#000000/20, #FFFFFF/30)
|
|
23
|
-
.main-flag mr:10px rd:50% w:20px h:20px
|
|
24
|
-
.main-name mr:10px
|
|
25
|
-
.main-arrow w:16px h:16px fill:light-dark(#000000,#FFFFFF) ml:auto scale-y:-1 ead:$ease
|
|
26
|
-
.menu t:100% l:50% x:-50% zi:999 backdrop-filter:blur(20px) mt:2px rd:8px rd:8px py:5px bgc:light-dark(#000000/5, #FFFFFF/10) fw:500 fs:13px ead:$ease
|
|
27
|
-
.menu-item d:hflex ai:center px:10px py:5px rd:8px cursor:pointer bg@hover:light-dark(#000000/10, #FFFFFF/20) m:5px
|
|
28
|
-
.menu-item-icon h:20px w:20px mr:10px rd:50%
|
|
29
|
-
.menu-item-text fs:13px
|
|
30
|
-
|
|
31
|
-
def icon country
|
|
32
|
-
return icons.replace('##',country)
|
|
33
|
-
|
|
34
|
-
def mouseleave e
|
|
35
|
-
const rect = self.getBoundingClientRect!
|
|
36
|
-
const menu = $menu.getBoundingClientRect!
|
|
37
|
-
const inside = e.clientY >= menu.bottom || e.clientY <= rect.top || (e.clientX <= rect.left and e.clientY <= rect.bottom) || (e.clientX <= menu.left and e.clientY >= menu.top) || (e.clientX >= rect.right and e.clientY <= rect.bottom) || (e.clientX >= menu.right and e.clientY >= menu.top)
|
|
38
|
-
#dropdown = !inside
|
|
39
|
-
|
|
40
|
-
<self [pos:rel] @mouseenter=(#dropdown = true) @mouseleave=mouseleave>
|
|
41
|
-
<div.main [pos:rel d:hcc] .main-active=#dropdown>
|
|
42
|
-
<img.main-flag src=icon(state[state.active].$.flag)>
|
|
43
|
-
<div.main-name> state.$.name
|
|
44
|
-
<{icon-arrow}.main-arrow [scale-y:1]=#dropdown>
|
|
45
|
-
|
|
46
|
-
if #dropdown
|
|
47
|
-
<div$menu.menu [pos:abs w:100% > max-content o@off:0] ease>
|
|
48
|
-
for own key, value of state.languages
|
|
49
|
-
<div.menu-item @click=onselect(key) [d:none]=(key == state.active)>
|
|
50
|
-
<img.menu-item-icon src=icon(value.$.flag)>
|
|
51
|
-
<span.menu-item-text> value.$.name
|