Swift 3: How to get language code from a country code? - ios

I want to get the main language of a country. For example: "US" -> "en" or "VN" -> "vi" In Swift 3, are there any ways to do this?

The system has a list of common locales that include both a language and region. You can use this to get common languages for a region. There is no concept of a main language in a Locale.
func commonLanguages(for region:String) -> [String] {
return Locale.availableIdentifiers
.map { Locale(identifier:$0) }
.filter { $0.regionCode == region }
.map { $0.languageCode ?? "??" }
}

You can use a predefined language code list to identify the language code
let array: [String] = [
"af-ZA",
"am-ET",
"ar-AE",
"ar-BH",
"ar-DZ",
"ar-EG",
"ar-IQ",
"ar-JO",
"ar-KW",
"ar-LB",
"ar-LY",
"ar-MA",
"arn-CL",
"ar-OM",
"ar-QA",
"ar-SA",
"ar-SY",
"ar-TN",
"ar-YE",
"as-IN",
"az-Cyrl-AZ",
"az-Latn-AZ",
"ba-RU",
"be-BY",
"bg-BG",
"bn-BD",
"bn-IN",
"bo-CN",
"br-FR",
"bs-Cyrl-BA",
"bs-Latn-BA",
"ca-ES",
"co-FR",
"cs-CZ",
"cy-GB",
"da-DK",
"de-AT",
"de-CH",
"de-DE",
"de-LI",
"de-LU",
"dsb-DE",
"dv-MV",
"el-GR",
"en-029",
"en-AU",
"en-BZ",
"en-CA",
"en-GB",
"en-IE",
"en-IN",
"en-JM",
"en-MY",
"en-NZ",
"en-PH",
"en-SG",
"en-TT",
"en-US",
"en-ZA",
"en-ZW",
"es-AR",
"es-BO",
"es-CL",
"es-CO",
"es-CR",
"es-DO",
"es-EC",
"es-ES",
"es-GT",
"es-HN",
"es-MX",
"es-NI",
"es-PA",
"es-PE",
"es-PR",
"es-PY",
"es-SV",
"es-US",
"es-UY",
"es-VE",
"et-EE",
"eu-ES",
"fa-IR",
"fi-FI",
"fil-PH",
"fo-FO",
"fr-BE",
"fr-CA",
"fr-CH",
"fr-FR",
"fr-LU",
"fr-MC",
"fy-NL",
"ga-IE",
"gd-GB",
"gl-ES",
"gsw-FR",
"gu-IN",
"ha-Latn-NG",
"he-IL",
"hi-IN",
"hr-BA",
"hr-HR",
"hsb-DE",
"hu-HU",
"hy-AM",
"id-ID",
"ig-NG",
"ii-CN",
"is-IS",
"it-CH",
"it-IT",
"iu-Cans-CA",
"iu-Latn-CA",
"ja-JP",
"ka-GE",
"kk-KZ",
"kl-GL",
"km-KH",
"kn-IN",
"kok-IN",
"ko-KR",
"ky-KG",
"lb-LU",
"lo-LA",
"lt-LT",
"lv-LV",
"mi-NZ",
"mk-MK",
"ml-IN",
"mn-MN",
"mn-Mong-CN",
"moh-CA",
"mr-IN",
"ms-BN",
"ms-MY",
"mt-MT",
"nb-NO",
"ne-NP",
"nl-BE",
"nl-NL",
"nn-NO",
"nso-ZA",
"oc-FR",
"or-IN",
"pa-IN",
"pl-PL",
"prs-AF",
"ps-AF",
"pt-BR",
"pt-PT",
"qut-GT",
"quz-BO",
"quz-EC",
"quz-PE",
"rm-CH",
"ro-RO",
"ru-RU",
"rw-RW",
"sah-RU",
"sa-IN",
"se-FI",
"se-NO",
"se-SE",
"si-LK",
"sk-SK",
"sl-SI",
"sma-NO",
"sma-SE",
"smj-NO",
"smj-SE",
"smn-FI",
"sms-FI",
"sq-AL",
"sr-Cyrl-BA",
"sr-Cyrl-CS",
"sr-Cyrl-ME",
"sr-Cyrl-RS",
"sr-Latn-BA",
"sr-Latn-CS",
"sr-Latn-ME",
"sr-Latn-RS",
"sv-FI",
"sv-SE",
"sw-KE",
"syr-SY",
"ta-IN",
"te-IN",
"tg-Cyrl-TJ",
"th-TH",
"tk-TM",
"tn-ZA",
"tr-TR",
"tt-RU",
"tzm-Latn-DZ",
"ug-CN",
"uk-UA",
"ur-PK",
"uz-Cyrl-UZ",
"uz-Latn-UZ",
"vi-VN",
"wo-SN",
"xh-ZA",
"yo-NG",
"zh-CN",
"zh-HK",
"zh-MO",
"zh-SG",
"zh-TW",
"zu-ZA"
];
var countryCode: String = "US";
for (index, languageCode) in array.enumerated() {
let languageComponent: [String] = languageCode.components(separatedBy: "-");
let lastElement = languageComponent[languageComponent.count - 1];
if (lastElement == countryCode) {
print(languageCode);
break;
}
}

Related

Text hyperlink hashtags(#) and mentions(#) in Jetpack Compose?

Text hyperlink hashtags(#) and mentions(#) in Jetpack Compose?
#Composable
fun HashtagsAndMentions() {
val colorScheme = MaterialTheme.colorScheme
val primaryStyle = SpanStyle(color = colorScheme.primary)
val textStyle = SpanStyle(color = colorScheme.onBackground)
val annotatedString = buildAnnotatedString {
withStyle(style = textStyle) {
append("I am ")
}
pushStringAnnotation(tag = "hashtags", annotation = "hashtags")
withStyle(style = primaryStyle) {
append(text = "#hashtags")
}
pop()
withStyle(style = textStyle) {
append(" and ")
}
pushStringAnnotation(tag = "mentions", annotation = "mentions")
withStyle(style = primaryStyle) {
append(text = "#mentions")
}
pop()
withStyle(style = textStyle) {
append(" in Jetpack Compose.")
}
}
ClickableText(
onClick = {
annotatedString.getStringAnnotations("hashtags", it, it).firstOrNull()?.let {
}
annotatedString.getStringAnnotations("mentions", it, it).firstOrNull()?.let {
}
},
text = annotatedString,
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.padding(16.dp))
}
#Preview
#Composable
fun PreviewTest() {
HashtagsAndMentions()
}
The above are fixed tags, how to dynamically identify and link?
ideas String to array
val string = "I am #hashtags and #mentions in Jetpack Compose."
val array = arrayOf("I am ", "#hashtags", " and ", "#mentions", "in Jetpack Compose.")
Here is an available hashtag and mention link.
Many thanks to #cyberpunk_unicorn for the idea, unfortunately his answer is not available, but I marked it anyway.
I refactored his code to ensure that it is runnable, concise enough, and very helpful to those who need it later.
This is a very flexible link scheme, you can add support for mobile phone numbers, emails, links, etc., as long as your regular expressions are correct, these links can be correctly identified.
#Composable
fun HashtagsMentionsTextView(text: String, modifier: Modifier = Modifier, onClick: (String) -> Unit) {
val colorScheme = MaterialTheme.colorScheme
val textStyle = SpanStyle(color = colorScheme.onBackground)
val primaryStyle = SpanStyle(color = colorScheme.blue)
val hashtags = Regex("((?=[^\\w!])[##][\\u4e00-\\u9fa5\\w]+)")
val annotatedStringList = remember {
var lastIndex = 0
val annotatedStringList = mutableStateListOf<AnnotatedString.Range<String>>()
// Add a text range for hashtags
for (match in hashtags.findAll(text)) {
val start = match.range.first
val end = match.range.last + 1
val string = text.substring(start, end)
if (start > lastIndex) {
annotatedStringList.add(
AnnotatedString.Range(
text.substring(lastIndex, start),
lastIndex,
start,
"text"
)
)
}
annotatedStringList.add(
AnnotatedString.Range(string, start, end, "link")
)
lastIndex = end
}
// Add remaining text
if (lastIndex < text.length) {
annotatedStringList.add(
AnnotatedString.Range(
text.substring(lastIndex, text.length),
lastIndex,
text.length,
"text"
)
)
}
annotatedStringList
}
// Build an annotated string
val annotatedString = buildAnnotatedString {
annotatedStringList.forEach {
if (it.tag == "link") {
pushStringAnnotation(tag = it.tag, annotation = it.item)
withStyle(style = primaryStyle) { append(it.item) }
pop()
} else {
withStyle(style = textStyle) { append(it.item) }
}
}
}
ClickableText(
text = annotatedString,
style = MaterialTheme.typography.bodyLarge,
modifier = modifier,
onClick = { position ->
val annotatedStringRange =
annotatedStringList.first { it.start < position && position < it.end }
if (annotatedStringRange.tag == "link") onClick(annotatedStringRange.item)
}
)
}
#Preview
#Composable
fun PreviewTest() {
val string = "I am #hashtags or #hashtags# and #mentions in Jetpack Compose. I am #hashtags or #hashtags# and #mentions in Jetpack Compose. 这是在 Jetpack Compose 中的一个 #标签 和 #提及 的超链接。 这是在 Jetpack Compose 中的一个 #标签 和 #提及 的超链接。"
HashtagsMentionsTextView(string, Modifier.padding(16.dp)) {
println(it)
}
}
preview effect

Metric math alarms: How can I use a for_each expression to loop over metrics within a dynamic block?

I am trying to create dynamic metric math alarms, that are configurable with a JSON.
I am struggling with looping over the metric alarm with a for_each expression as this is a loop within a loop.
Here is an example of what I am trying to do:
resource "aws_cloudwatch_metric_alarm" "Percentage_Alert" {
for_each = var.percentage_error_details
locals { alarm_details = each.value }
alarm_name = "${terraform.workspace}-${each.key}"
comparison_operator = local.alarm_details["Comparison_Operator"]
evaluation_periods = "1"
threshold = local.alarm_details["Threshold"]
metric_query {
id = "e1"
expression = local.alarm_details["Expression"]
label = local.alarm_details["Label"]
return_data = "true"
}
dynamic "metric_query" {
for metric in each.value["Metrics"]{
id = metric.key
metric_name = metric.value
period = local.alarm_details["Period"]
stat = local.alarm_details["Statistic"]
namespace = local.full_namespace
unit = "Count"
}
}
}
And this is the sample JSON
{
"locals": {
"Name": {
"Name": "metric_math",
"Metrics": {
"m1": "Sucess",
"m2": "Failure"
},
"Expression": "100*(m2/(m1+m2))",
"Threshold" : 1,
"Period": 25,
"Priority": "critical",
"Statistic": "Sum",
"Label": "label",
"Comparison_Operator": "GreaterThanOrEqualToThreshold"
}
}
}
And this is the error message i'm getting:
Error: Invalid block definition
On ../modules/cloudwatch/metriclogfilter/main.tf line 89: Either a quoted
string block label or an opening brace ("{") is expected here.
Any help would be much appreciated.

How to write a map to a YAML file in Dart

I have a map of key value pairs in Dart. I want to convert it to YAML and write into a file.
I tried using YAML package from dart library but it only provides methods to load YAML data from a file. Nothing is mentioned on how to write it back to the YAML file.
Here is an example:
void main() {
var map = {
"name": "abc",
"type": "unknown",
"internal":{
"name": "xyz"
}
};
print(map);
}
Expected output:
example.yaml
name: abc
type: unknown
internal:
name: xyz
How to convert the dart map to YAML and write it to a file?
It's a bit late of a response but for anyone else looking at this question I have written this class. It may not be perfect but it works for what I'm doing and I haven't found anything wrong with it yet. Might make it a package eventually after writing tests.
class YamlWriter {
/// The amount of spaces for each level.
final int spaces;
/// Initialize the writer with the amount of [spaces] per level.
YamlWriter({
this.spaces = 2,
});
/// Write a dart structure to a YAML string. [yaml] should be a [Map] or [List].
String write(dynamic yaml) {
return _writeInternal(yaml).trim();
}
/// Write a dart structure to a YAML string. [yaml] should be a [Map] or [List].
String _writeInternal(dynamic yaml, { int indent = 0 }) {
String str = '';
if (yaml is List) {
str += _writeList(yaml, indent: indent);
} else if (yaml is Map) {
str += _writeMap(yaml, indent: indent);
} else if (yaml is String) {
str += "\"${yaml.replaceAll("\"", "\\\"")}\"";
} else {
str += yaml.toString();
}
return str;
}
/// Write a list to a YAML string.
/// Pass the list in as [yaml] and indent it to the [indent] level.
String _writeList(List yaml, { int indent = 0 }) {
String str = '\n';
for (var item in yaml) {
str += "${_indent(indent)}- ${_writeInternal(item, indent: indent + 1)}\n";
}
return str;
}
/// Write a map to a YAML string.
/// Pass the map in as [yaml] and indent it to the [indent] level.
String _writeMap(Map yaml, { int indent = 0 }) {
String str = '\n';
for (var key in yaml.keys) {
var value = yaml[key];
str += "${_indent(indent)}${key.toString()}: ${_writeInternal(value, indent: indent + 1)}\n";
}
return str;
}
/// Create an indented string for the level with the spaces config.
/// [indent] is the level of indent whereas [spaces] is the
/// amount of spaces that the string should be indented by.
String _indent(int indent) {
return ''.padLeft(indent * spaces, ' ');
}
}
Usage:
final writer = YamlWriter();
String yaml = writer.write({
'string': 'Foo',
'int': 1,
'double': 3.14,
'boolean': true,
'list': [
'Item One',
'Item Two',
true,
'Item Four',
],
'map': {
'foo': 'bar',
'list': ['Foo', 'Bar'],
},
});
File file = File('/path/to/file.yaml');
file.createSync();
file.writeAsStringSync(yaml);
Output:
string: "Foo"
int: 1
double: 3.14
boolean: true
list:
- "Item One"
- "Item Two"
- true
- "Item Four"
map:
foo: "bar"
list:
- "Foo"
- "Bar"
package:yaml does not have YAML writing features. You may have to look for another package that does that – or write your own.
As as stopgap, remember JSON is valid YAML, so you can always write out JSON to a .yaml file and it should work with any YAML parser.
I ran into the same issue and ended up hacking together a simple writer:
// Save the updated configuration settings to the config file
void saveConfig() {
var file = _configFile;
// truncate existing configuration
file.writeAsStringSync('');
// Write out new YAML document from JSON map
final config = configToJson();
config.forEach((key, value) {
if (value is Map) {
file.writeAsStringSync('\n$key:\n', mode: FileMode.writeOnlyAppend);
value.forEach((subkey, subvalue) {
file.writeAsStringSync(' $subkey: $subvalue\n',
mode: FileMode.writeOnlyAppend);
});
} else {
file.writeAsStringSync('$key: $value\n',
mode: FileMode.writeOnlyAppend);
}
});
}

Dynamic cell color in jspdf autoTable?

Is it possible to define the cell color with a nested property of the object mapped to the table ?
The JSON structure of the objects is :
objects: [
{
"agent": "agent_1",
"days": {
day_0: {
"code": "ABC",
"color": "#0062cc"
},
day_1: {
"code": "DEF",
"color": "#a09494b2"
}
},
{
[...]
}
]
I have a table defined like this :
let columns = [
{title: "Agent", dataKey: "agent"},
{title: "january 1st", dataKey: "day_0"},
{title: "january 2nd", dataKey: "day_1"}]
let rows = [
{agent: "agent_1", day_0: "ABC", day_1: "DEF"},
[...]
]
All that works fine. But I'd like to set the color of each day cell dynamically, set with the color code of the corresponding object. Something like :
createdCell: function(cell, data) {
{
cell.styles.fillColor = "day_0.color";
}
}
But I can't figure how to pass the data to the table. Is it possible ? Can displayProperty help in any way ?
EDIT: In this case it was that v2.3.4 of jspdf-autotable was needed
Based on our comments discussion I think I understood your problem. You can try something like this (with the hexToRgb function from here)
let columns = [{
title: "Agent",
dataKey: "agent"
},
{
title: "january 1st",
dataKey: "day_0"
},
{
title: "january 2nd",
dataKey: "day_1"
}
]
let objects = [{
agent: "agent_1",
day_0: {
"code": "ABC",
"color": "#00ff00"
},
day_1: {
"code": "DEF",
"color": "#ff0000"
}
// etc
}];
let doc = jsPDF()
doc.autoTable(columns, objects, {
createdCell: function(cell, data) {
let hex = cell.raw.color
if (hex) {
let rgb = hexToRgb(hex)
cell.styles.fillColor = rgb;
cell.text = cell.raw.code
}
}
});
doc.save('jhg.pdf')
function hexToRgb(hex) {
var bigint = parseInt(hex.replace('#', ''), 16);
var r = (bigint >> 16) & 255;
var g = (bigint >> 8) & 255;
var b = bigint & 255;
return [r, g, b];
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.4.1/jspdf.debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/2.3.4/jspdf.plugin.autotable.js"></script>
I just leave the answer here just in case anyone needs it.
We can use the didParseCell hook.
doc.autoTable({
head: [[..., color]],
body: [[..., #ffffff], [..., #ff0000]], // pass hexa value to the cell
didParseCell: function (HookData) {
if (HookData.cell == undefined)
return;
// find cell taht contains the hexa value
// the change the fillColor property
// and set the cell value to empty
var color = HookData.cell.text[0];
if (color.match(/^#[a-fA-F0-9]{3}([a-fA-F0-9]{3})/g) != null) {
HookData.cell.styles.fillColor = hexToRgb(color);
HookData.cell.text = [];
}
}
});
Code to convert hexa to RGB:
hexToRgb(hex) {
var bigint = parseInt(hex.replace('#', ''), 16);
var r = (bigint >> 16) & 255;
var g = (bigint >> 8) & 255;
var b = bigint & 255;
return [r, g, b];
}
Package version:
jspdf : 2.5.1
jspdf-autotable :3.5.25

How to group non-empty lines with PEG.js

I'm trying to parse a categories file with PEG.js
How can I group categories (set of non-empty lines followed by a blank line)
stopwords:fr:aux,au,de,le,du,la,a,et,avec
synonyms:en:flavoured, flavored
synonyms:en:sorbets, sherbets
en:Artisan products
fr:Produits artisanaux
< en:Artisan products
fr:Gressins artisanaux
en:Baby foods
fr:Aliments pour bébé, aliment pour bébé, alimentation pour bébé, aliment bébé, alimentation bébé, aliments bébé
< en:Baby foods
fr:Céréales pour bébé, céréales bébé
< en:Whisky
fr:Whisky écossais
es:Whiskies escoceses
wikipediacategory:Q8718387
For now I can parse line by line with this code:
start = stopwords* synonyms* category+
language_and_words = l:[^:]+ ":" w:[^\n]+ {return {language: l.join(''), words: w.join('')};}
stopwords = "stopwords:" w:language_and_words "\n"+ {return {stopwords: w};}
synonyms = "synonyms:" w:language_and_words "\n"+ {return {synonyms: w};}
category_line = "< "? w:language_and_words "\n"+ {return w;}
category = c:category_line+ {return c;}
I got:
{
"language": "en",
"words": "Artisan products"
},
{
"language": "fr",
"words": "Produits artisanaux"
}
but I want (for each group):
{
{
"language": "en",
"words": "Artisan products"
},
{
"language": "fr",
"words": "Produits artisanaux"
}
}
I tried this too, but it doesn't group and I got \n at the beginning of some lines.
category_line = "< "? w:language_and_words "\n" {return w;}
category = c:category_line+ "\n" {return c;}
I found a partial solution:
start = category+
word = c:[^,\n]+ {return c.join('');}
words = w:word [,]? {return w.trim();}
parent = p:"< "? {return (p !== null);}
line = p:parent w:words+ "\n" {return {parent: p, words: w};}
category = l:line+ "\n"? {return l;}
I can parse this...
< fr:a,b
fr:aa,bb
en:d,e,f
fr:dd,ee, ffff
and get grouped:
[
[ {...}, {...} ],
[ {...}, {...} ]
]
But there is a problem with "lang:" at the beginning of each category, if I try to parse "lang:" my catégories are not grouped...
I find it's useful to break down iteratively the parse (problem decomposition, old-school à la Wirth). Here's a partial solution that I think gets you in the right direction (I didn't parse the Line elements of categories.
start =
stopwords
synonyms
category+
category "category"
= category:(Line)+ categorySeparator { return category }
stopwords "stopwords"
= stopwordLine*
stopwordLine "stopword line"
= stopwordLine:StopWordMatch EndOfLine* { return stopwordLine }
StopWordMatch
= "stopwords:" match:Text { return match }
synonyms "stopwords"
= synonymLine*
synonymLine "stopword line"
= synonymLine:SynonymMatch EndOfLine* { return synonymLine }
SynonymMatch
= "synonyms:" match:Text { return match }
Line "line"
= line:Text [\n] { return line }
Text "text"
= [^\n]+ { return text() }
EndOfLine "(end of line)"
= '\n'
EndOfFile
= !. { return "EOF"; }
categorySeparator "separator"
= EndOfLine EndOfLine* / EndOfLine? EndOfFile
My use of mixed case is arbitrary and not very stylish.
There's also a way to save the solutions online: http://peg.arcanis.fr/2WQ7CZ/

Resources