Dynamic struct member names like in javascript in golang - oop

I am writing a multi-lang website.
I read the language info from users cookies, and I have several translation modules such as en.go gr.go etc.
The modules are of type map[string]string.The problem here is in javascript I can do something like lang[cookies.lang]["whatever message"].'But go does not support accessing struct members in this way.
I could make switch case ormap[string]map[string]string` and map all possible languages, but this is much extra work.
So is there any way golang provides some way to access members like js brackets notation?
Not: There was a similar question on the stack, and somebody wrote to use "reflect" package, but I could not quite understand how it works and failed to reproduce by myself works and failed to reproduce by myself.

One possible route would be to use a map[string]map[string]string.
You could then have a base package in which you declare your base translation variable and in your translation modules, you can use an init function to populate the relevant sub-map. It's essentially optional if you want to do this as separate packages or just separate files (doing it as packages means you have better compile-time control of what languages to include, doing it as files is probably less confusing).
If you go the packages root, I suggest the following structure:
translation/base This is where you export from
translation/<language> These are "import only" packages
Then, in translation/base:
package "base"
var Lang map[string]map[string]string
And in each language-specific package:
package "<language code>"
import "language/base"
var code = "<langcode>"
func init() {
d := map[string]string{}
d[<phrase1>] = "your translation here"
d[<phrase2>] = "another translation here"
// Do this for all the translations
base.Lang[code] = d
}
Then you can use this from your main program:
package "..."
import (
"language/base"
_ "language/lang1" // We are only interested in side-effects
_ "language/lang2" // Same here...
)
Not using separate packages is (almost) the same. You simply ensure that all the files are in the same package and you can skip the package prefix for the Lang variable.
A toy example on the Go Playground, with all the "fiddly" bits inlined.

Related

Merge styles - How to use vendor prefixes

I'm using this library #uifabric/merge-styles from office-ui-fabric. My question is how to use vendor prefixes inside mergeStyleSets?
Example -webkit-filter:
import { mergeStyleSets } from '#uifabric/merge-styles'
mergeStyleSets({
webkitFilter: 'blur(5px)', // Error! No Typescript definition.
})
Is there any other way to achieve this?
Merge Styles Library
It looks like there is no Typescript definitions for it
IRawStyleBase.ts
Addition to #Vitalie Braga answer:
This is temporary solution if you are using Typescript project:
const foo = mergeStyleSets({
root: [
{
backgroundColor: '#f00',
...({ '-webkit-filter': 'blur(5px)' } as any)
},
]
})
Issues Page - Git OFFICE UI FABRIC
#uifabric/merge-styles library has smarts about automatic vendor prefixing for you but the only issue with that is that the rules that are auto-prefixed today are limited to just one: user-select. I would advise you go and submit an issue in their github repo here and either ask if new rules can be added or ask how to handle this situation.
From a deeper investigation looks like they have some vendor specific support but is very limited in IRawStyleBase.ts. Those rules will automatically be transformed into vendor rules.
So to answer your questions if you are using a TS project there is no way you can specify something that is not compatible with the IRawStyleBase interface but if you are using a js script you can probably try your luck as I did in this code-sandbox and it looks like the filter get's through but nothing else.

Module dependencies: is it possible to set a mininum version?

Is it possible to add a minimum version to a module listed in the depend section of a META6.json file?
It uses the same syntax as the Version class. You can use, for instance, v1.0+, or, in META6.json, simply "1.0+"
To declare a dependency on Foo of version 1 or higher one would do the same as if one was asking zef to install Foo:ver<1.0+>:
zef install "Foo:ver<1.0+>"
"depends" : [
"Foo:ver<1.0+>"
]
Long form identities use version literals for api and ver attributes, and strings for any other (such as auth, file, name, etc). So to describe such a dependency you should write it the same way you would if you were useing it using the literal form :foo<...> ala use Test:ver<6.d+>. This is opposed to :foo(...) form which can run anything, e.g. use Test:ver(do { say 42; v6.d+ }), which would allow arbitrary code execution by just searching for dependencies and thus is not a valid way to describe something in a META6.json

Accessing resources of a dynamically loaded module

I can't find a way to correctly get access to resources of an installed distribution. For example, when a module is loaded dynamically:
require ::($module);
One way to get hold of its %?RESOURCES is to ask module to have a sub which would return this hash:
sub resources { %?RESOURCES }
But that adds extra to the boilerplate code.
Another way is to deep scan $*REPO and fetch module's distribution meta.
Are there any better options to achieve this task?
One way is to use $*REPO ( as you already mention ) along with the Distribution object that CompUnit::Repository provides as an interface to the META6 data and its mapping to a given data store / file system.
my $spec = CompUnit::DependencySpecification.new(:short-name<Zef>);
my $dist = $*REPO.resolve($spec).distribution;
say $dist.content("resources/$_").open.slurp for $dist.meta<resources>.list;
Note this only works for installed distributions at the moment, but would work for not-yet-installed distributions ( like -Ilib ) with https://github.com/rakudo/rakudo/pull/1812

Accessing custom jbake confing properties in asciidoc

After some time I spent staring at the jbake code, I figured out that if I declare my own property in jbake.properties :
...
foo=bar
...
I can reuse that in files that go through a template engine by referencing it as ${config.foo}. I'd like to have this substitution working also on the content lvl, i.e. for files written in asciidoc, living inside the content directory.
Is there any non-trivial way to achieve it? How can I make the templating engine to proccess the result of asciidoc parses engine, or make it running it before the asciidoctor?
I found the answer myself.
To use the property substitution in asciidoc files, add following to the jbake.properties:
...
asciidoctor.attributes.export=true
foo=world
...
and reference the variable in aFile.adoc this way:
Hello {foo}!

Can anyone explain what es7 reflect-metadata is all about?

Been studying ES6, JSPM & angular2 for a week now and I found this repo ES6-loader
if we look at the index.html at the bottom script you'll see
System.import('reflect-metadata')
.then(function() {
return System.import('app/index');
})
.catch(console.log.bind(console));
This is using JSPM's systemjs polyfill to get ES6's import.
Question: What is the reflect-metadata really do in this situation? npm reflect-meta The more I read the documentation, the less I understand what it does?
'reflect-metadata' is a package that is a proposal for ES7. It allow for meta data to be included to a class or function; essentially it is syntax sugar.
Example.
Angular 2 ES6:
#Component({selector: "thingy"})
#View({template: "<div><h1>Hello everyone</h1></div>"})
class Thingy{};
As you can see there are no semicolons after #Component and #View. This is because they are essentially Chains of (meta)data on the class.
Now lets look at that same code in Angular 2 but in ES5:
function Thingy(){}
Thingy.annotations = [
new angular.ComponentAnnotation({
selector: "thingy"
}),
new angular.ViewAnnotation({
template: "<div><h1>Hello everyone</h1></div>"
})
];
As you can see the # symbol abstracts out alot of the annotations property of a class and makes it More D.R.Y.
Taking this one step further Angular team knows that annotations are a bit abstract for the new user. Moreover, the ES5 is just too verbose. which is why they made a.js which will make interfacing with annotations better:
Video to understand this