Skip to content

Commit 36db8f1

Browse files
authored
Merge pull request #16 from tobozo/1.4.0
1.4.0
2 parents 3c93b4e + 1bb47b2 commit 36db8f1

File tree

10 files changed

+2339
-1557
lines changed

10 files changed

+2339
-1557
lines changed

ReadMe.md

+114-41
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@ This arduino library is based on [libyaml](https://github.com/yaml/libyaml).
1616
- RP2040
1717
- ESP8266
1818
- SAMD
19+
- TeensyDuino
1920

2021
### Features:
2122

2223
- YAML➔JSON and JSON➔YAML conversion
24+
- Accepts *valid* JSON or YAML as the input.
25+
- Standalone serializers/deserializers
2326
- ArduinoJson serializers/deserializers
2427
- cJSON serializers/deserializers
25-
28+
- Node accessors
29+
- l10n style gettext()
30+
- i18n loader
2631

2732
----------------------------
2833

@@ -31,14 +36,12 @@ This arduino library is based on [libyaml](https://github.com/yaml/libyaml).
3136

3237
```cpp
3338
#include <ArduinoYaml.h>
34-
3539
```
3640

3741
or
3842

3943
```cpp
4044
#include <YAMLDuino.h>
41-
4245
```
4346

4447
----------------------------
@@ -49,35 +52,38 @@ or
4952
YAML is a superset of JSON, so native conversion from/to JSON is possible without any additional JSON library.
5053

5154
```cpp
52-
// JSON <=> YAML stream to stream conversion (both ways!).
53-
// Accepts valid JSON or YAML as the input.
5455
// Available values for output format:
55-
// YAMLParser::OUTPUT_YAML
56-
// YAMLParser::OUTPUT_JSON
57-
// YAMLParser::OUTPUT_JSON_PRETTY
58-
size_t serializeYml( Stream &source, Stream &destination, OutputFormat_t format );
56+
// OUTPUT_YAML (default)
57+
// OUTPUT_JSON
58+
// OUTPUT_JSON_PRETTY
59+
// JSON/YAML document to YAML/JSON string
60+
size_t serializeYml( yaml_document_t* src_doc, String &dest_string, OutputFormat_t format=OUTPUT_YAML );
61+
// JSON/YAML object to YAML/JSON stream
62+
size_t serializeYml( yaml_document_t* src_doc, Stream &dest_stream, OutputFormat_t format=OUTPUT_YAML );
63+
64+
// YAML stream to YAML document
65+
int deserializeYml( YAMLNode& dest_obj, const char* src_yaml_str );
66+
// YAML string to YAML document
67+
int deserializeYml( YAMLNode& dest_obj, Stream &src_stream );
5968

6069
```
6170
6271
6372
**Convert YAML to JSON**
6473
```cpp
6574
String yaml_str = "hello: world\nboolean: true\nfloat: 1.2345";
66-
StringStream yaml_stream( yaml_str );
67-
68-
serializeYml( yaml_stream, Serial, YAMLParser::OUTPUT_JSON_PRETTY );
69-
75+
YAMLNode yamlnode = YAMLNode::loadString( yaml_str );
76+
serializeYml( yamlnode.getDocument(), Serial, OUTPUT_JSON_PRETTY ); // pretty JSON
77+
// serializeYml( yamlnode.getDocument(), Serial, OUTPUT_JSON ); // ugly JSON
7078
```
7179

7280

7381

7482
**Convert JSON to YAML**
7583
```cpp
7684
String json_str = "{\"hello\": \"world\", \"boolean\": true, \"float\":1.2345}";
77-
StringStream json_stream( json_str );
78-
79-
serializeYml( json_stream, Serial, YAMLParser::OUTPUT_YAML );
80-
85+
YAMLNode yamlnode = YAMLNode::loadString( yaml_str );
86+
serializeYml( yamlnode.getDocument(), Serial, OUTPUT_YAML );
8187
```
8288
8389
----------------------------
@@ -123,9 +129,9 @@ See the [motivational post](https://github.com/bblanchon/ArduinoJson/issues/1808
123129

124130
ArduinoJson support is implicitely enabled on most platforms except for ESP32 where dependencies can be detected.
125131

132+
*****ESP32 plaforms must include ArduinoJson.h before ArduinoYaml.h or bindings will be disabled!******
126133

127134
```cpp
128-
// ESP32 plaforms must include ArduinoJson before ArduinoYaml or functions will be disabled
129135
#include <ArduinoJson.h>
130136
#include <ArduinoYaml.h>
131137
```
@@ -172,6 +178,8 @@ size_t serializeYml( cJSON* src_obj, Stream &dest_stream );
172178
int deserializeYml( cJSON* dest_obj, const char* src_yaml_str );
173179
// YAML stream to cJSON object
174180
int deserializeYml( cJSON* dest_obj, Stream &src_stream );
181+
// YAML document to cJSON object
182+
int deserializeYml( cJSON** dest_obj, yaml_document_t* src_document );
175183
176184
```
177185

@@ -235,7 +243,7 @@ Set custom JSON indentation and folding depth:
235243
236244
```cpp
237245
// this set two spaces per indentation level, unfolds up to 8 nesting levels
238-
YAMLParser::setJSONIndent(" ", 8 ); // lame fact: folds on objects, not on arrays
246+
YAML::setJSONIndent(" ", 8 ); // lame fact: folds on objects, not on arrays
239247
240248
```
241249

@@ -251,43 +259,106 @@ YAML::setYAMLIndent( 3 );
251259
252260
----------------------------
253261
262+
## YAML gettext Module
263+
264+
The gettext module is a member of YAMLNode object.
265+
266+
```cpp
267+
class YAMLNode
268+
{
269+
// (...)
270+
public:
271+
const char* gettext( const char* path, char delimiter=':' );
272+
// YAMLNode objects also bring few interesting methods to scope:
273+
const char* scalar();
274+
size_t size();
275+
bool isScalar();
276+
bool isSequence();
277+
bool isMap();
278+
bool isNull();
279+
// (...)
280+
}
281+
```
282+
283+
#### Usage (persistent)
284+
285+
Load from string:
286+
```cpp
287+
YAMLNode yamlnode = YAMLNode::loadString( yaml_or_json_string );
288+
```
289+
290+
Load from stream:
291+
```cpp
292+
YAMLNode yamlnode = YAMLNode::loadStream( yaml_or_json_stream );
293+
```
294+
295+
296+
Access a value:
297+
```cpp
298+
const char* text = yamlnode.gettext( "path:to:property:name" );
299+
```
300+
301+
#### Usage (non persistent)
302+
303+
YAMLNode supports chaining:
304+
305+
```cpp
306+
// load yaml and extract value from 'stuff'
307+
YAMLNode::loadString("blah:\n stuff:\n true\n").gettext("blah:stuff");
308+
// load json and extract value from 'stuff'
309+
YAMLNode::loadString("{\"blah\":{\"stuff\":\"true\"}}").gettext("blah:stuff");
310+
```
311+
312+
313+
## I18N/L10N with gettext Module
314+
315+
Note: i18n Support is disabled with WIO Terminal (platform needs a proper `fs::FS` filesystem implementation).
316+
WIO Terminal can still use the native `YAMLNode::gettext()` though.
254317
255-
## I18N and L10N
256318
257-
Note: Support is disabled with WIO Terminal (needs a proper fs::FS implementation).
319+
#### Usage
258320
259-
* Load the module with `#include <i18n/i18n.hpp>`.
260-
* Assign a filesystem with `i18n.setFS()`.
261-
* Load a locale with `i18n.setLocale()`.
321+
* Include ArduinoJson and a `fs::FS` filesystem first
322+
* Create an i18n instance and assign the filesystem `i18n_t i18n( &LittleFS );`.
323+
* Load `en-GB` locale with `i18n.setLocale("en-GB")`.
262324
* Use `i18n.gettext()` to access localized strings.
263325
264326
327+
#### Example
328+
329+
YAML Sample `/lang/en-GB.yml` stored in LittleFS:
330+
331+
```yml
332+
en-GB:
333+
hello: world
334+
blah:
335+
my_array:
336+
- first
337+
- second
338+
- third
339+
340+
```
341+
342+
Load the language file and access translations:
343+
344+
265345
```cpp
266346

267-
#include <LittleFS.h>
268-
#include <ArduinoJson.h>
269-
#define YAML_DISABLE_CJSON // not needed here
270-
#include <YAMLDuino.h>
271-
#include <i18n/i18n.hpp>
347+
#include <LittleFS.h> // Mandatory filestem (can be SPIFFS, SD, SD_MMC, LittleFS)
348+
#include <YAMLDuino.h> // Load the library
272349

273-
// Sample example `/lang/en-GB.yml` stored in LittleFS:
274-
//
275-
// en-GB:
276-
// hello: world
277-
// blah:
278-
// my_array:
279-
// - first
280-
// - second
281-
// - third
282350

351+
i18n_t i18n( &LittleFS ); // Create an i18n instance attached to filesystem
283352

284353
void setup()
285354
{
286355
Serial.begin(115200);
287356
LittleFS.begin();
288357

289-
i18n.setFS( &LittleFS ); // assign LittleFS
290-
i18n.setLocale("en-GB"); // will load "/lang/en-GB.yml" language file
358+
// i18n.setFS( &SD ); // change filesystem to SD
359+
i18n.setLocale("en-GB"); // This will look for "en-GB.yml" language file in "/lang/" folder and set "en-GB" as locale
360+
// i18n.setLocale("/lang/en-GB.yml"); // This will load "/lang/en-GB.yml" language file and set "en-GB" as locale
361+
// i18n.setLocale("en-GB", "/non-locale/file.yml"); // This will set "en-GB" as locale and load arbitrary "/non-locale/file.yml" language file
291362

292363
Serial.println( i18n.gettext("hello" ) ); // prints "world"
293364
Serial.println( i18n.gettext("blah:my_array:2" ) ); // prints "third"
@@ -327,7 +398,7 @@ Set library debug level:
327398
// LogLevelInfo : Errors+Warnings+Info
328399
// LogLevelDebug : Errors+Warnings+Info+Debug
329400
// LogLevelVerbose : Errors+Warnings+Info+Debug+Verbose
330-
YAMLParser::setLogLevel( YAML::LogLevelDebug );
401+
YAML::setLogLevel( YAML::LogLevelDebug );
331402
```
332403
333404
----------------------------
@@ -355,6 +426,7 @@ project. Thanks in advance!
355426
- [@DaveGamble](https://github.com/DaveGamble)
356427
- [@bblanchon](https://github.com/bblanchon)
357428
- [@vikman90](https://github.com/vikman90/yaml2json)
429+
- [@Visse](https://github.com/Visse/libyaml-cpp)
358430
359431
360432
@@ -364,3 +436,4 @@ project. Thanks in advance!
364436
- ArduinoStreamUtils : https://github.com/bblanchon/ArduinoStreamUtils
365437
- cJSON : https://github.com/DaveGamble/cJSON
366438
- libyaml : https://github.com/yaml/libyaml
439+

examples/i18n/i18n.ino

+46-14
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,67 @@
11
#include <LittleFS.h>
2-
#include <ArduinoJson.h>
3-
#define YAML_DISABLE_CJSON // not needed here
42
#include <YAMLDuino.h>
5-
#include <i18n/i18n.hpp>
63

4+
#include <vector>
5+
static std::vector<String> i18nFiles;
6+
7+
const char* extension = "yml";
8+
const char* path = "/lang";
9+
10+
i18n_t i18n( &LittleFS ); // attach LittleFS to i18n loader
711

812
void setup()
913
{
1014
Serial.begin(115200);
11-
12-
Serial.printf( "[%d] %s\n", ESP.getFreeHeap(), "Hello i18n test");
13-
1415
LittleFS.begin();
1516

16-
i18n.setFS( &LittleFS );
17+
Serial.println( "Hello i18n test");
1718

18-
if(! i18n.setLocale("fr-FR") ) {
19+
// scan the lang folder and store filenames in an array
1920

20-
Serial.printf( "[%d] %s\n", ESP.getFreeHeap(), "Error loading locale, halting");
21+
File dir = LittleFS.open( path );
2122

23+
if( !dir ) {
24+
Serial.println("Error, can't access filesystem, halting");
2225
while(1) vTaskDelay(1);
2326
}
2427

25-
Serial.printf( "[%d] %s\n", ESP.getFreeHeap(), "Locale loaded");
28+
while (true) {
29+
File entry = dir.openNextFile();
30+
if (! entry) { // no more files
31+
break;
32+
}
33+
if (entry.isDirectory()) continue;
34+
35+
String fileName = entry.path();
36+
if( fileName.endsWith( extension ) ) {
37+
i18nFiles.push_back( fileName );
38+
}
39+
entry.close();
40+
}
41+
42+
dir.close();
2643
}
2744

2845

2946
void loop()
3047
{
31-
Serial.printf( "[%d] %s\n", ESP.getFreeHeap(), i18n.gettext("activerecord:errors:messages:record_invalid" ) ); // "La validation a échoué : %{errors}"
32-
Serial.printf( "[%d] %s\n", ESP.getFreeHeap(), i18n.gettext("date:abbr_day_names:2" ) ); // "mar"
33-
Serial.printf( "[%d] %s\n", ESP.getFreeHeap(), i18n.gettext("time:pm" ) ); // "pm", last element
34-
delay(1000);
48+
int randLang = rand()%(i18nFiles.size());
49+
50+
int free_heap_before_load = HEAP_AVAILABLE();
51+
52+
if(! i18n.setLocale(i18nFiles[randLang].c_str()) ) {
53+
54+
YAML_LOG_n( "Error loading locale %s, halting\n", i18nFiles[randLang].c_str());
55+
56+
while(1) vTaskDelay(1);
57+
}
58+
59+
int free_heap_after_load = HEAP_AVAILABLE();
60+
61+
YAML_LOG_n( "[%d-%d] Locale file %s loaded\n", free_heap_before_load, free_heap_after_load, i18nFiles[randLang].c_str());
62+
63+
Serial.println( i18n.gettext("activerecord:errors:messages:record_invalid" ) ); // "La validation a échoué : %{errors}"
64+
Serial.println( i18n.gettext("date:abbr_day_names:2" ) ); // "mar"
65+
Serial.println( i18n.gettext("time:pm" ) ); // "pm", last element
66+
delay( 1000 );
3567
}

0 commit comments

Comments
 (0)