How to change the SAPUI5 language? - internationalization

I am searching for a way to change the language used in SAPUI5 "completely".
To change the language using a property file seems not to be a problem, a working example:
new sap.m.Switch({
state : false,
customTextOn : "EN",
customTextOff : "DE",
visible : true,
change : [ function(oEvent) {
var control = oEvent.getSource();
var state = control.getState();
if (state) {
i18nModel = new sap.ui.model.resource.ResourceModel({bundleUrl:"i18n/i18n.properties", bundleLocale:"en"});
sap.ui.getCore().setModel(i18nModel, "i18n");
} else {
i18nModel = new sap.ui.model.resource.ResourceModel({bundleUrl:"i18n/i18n.properties", bundleLocale:"de"});
sap.ui.getCore().setModel(i18nModel, "i18n");
}
}, this ]
}),
Pressing the switch button will immediately change the text bound to "i18n>" model.
The problem is, that I also have text from metadata (especially lables) from the oData service.
A binding path could look like this:
{modelName>/#Entity/Attribute/#sap:label}
The language for this is defined during first logon. Now I am searching for a way to reload metadata (and also data) after a language change.
Is there any way to do so? Or is the only way to logout and login again?

You may need to reinit the ODataModel
var oModel = new sap.ui.model.odata.ODataModel("/your_odata_service",
{metadataUrlParams:{"sap-language":"de"}}
);
This way it will retrieve the OData metadata for German via $metadata?sap-language=de again.
It just comes off the top of my mind. You can have a try.

Thanks! I've had an issue to change the language that smartforms/smartfields are using for labels, as i couldn't control the language in which the labels were stated in the metadata.xml file. Allen solution worked for me! I am using the SAP Web IDE and i changed the manifest.json file adding this line were the principle or main (nameless, "") model is defined:
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "mpo.i18n.i18n"
}
},
"": {
"dataSource": "mainService",
"settings": {
"defaultBindingMode": "TwoWay",
"metadataUrlParams": {
"sap-documentation": "heading",
"sap-language": "en"
}
},
Thanks Allen!

Allen is almost right.
In order to reload the metadata file with the additional sap-language parameter, you need to destroy the model first and then reinit the new one. It is important, that you don't have any other ODataModel instance of the same service.
this.getModel().destroy();
var oModel = new sap.ui.model.odata.v2.ODataModel("/youService", {
metadataUrlParams: {"sap-language":"de"}
});

Related

Springdocs: Specifying an explicit type for Paged responses

I'm working on a "global search" for my application.
Currently, I'm using hibernate-search to search for instances of multiple different objects and return them to the user.
The relevant code looks as follows:
Search.session(entityManager)
.search(ModelA.classs, ModelB.class)
.where(...)
.sort(...)
.fetch(skip, count);
Skip and count are calculated based on a Pageable and the result is used to create an instance of Page, which will be returned to the controller.
This works as I'd expect, however, the types generated by swagger-docs obviously doesn't know, what the type within the Page is, and therefore uses Object.
I'd like to expose the correct types, as I use them to generate the types for the frontend application.
I was able to set the type to an array, when overwriting the schema like this:
#ArraySchema(schema = #Schema(anyOf = {ModelA.class, ModelB.class}))
public Page<?> search(Pageable pageable) {
However, this just disregards the Page and also isn't correct.
The next thing I tried is extending the PageImpl, overwriting the getContent method, and specifying the same schema on this method, but this wasn't included in the output at all.
Next was implementing Page<T> myself (and later removing the implements reference to Page<T>) and specifying the same schema on getContent, iterator, and the field itself, but also to no effect.
How do I tell spring-docs, what the content of the resulting Page might be?
I stumbled upon this when trying to solve a similar problem
Inspired from this thread Springdoc with a generic return type i came up with the following solution, and it seems to apply to your case also. Code examples are in Kotlin.
I introduced a stub class that will just act as the Schema for the response:
private class PageModel(
#Schema(oneOf = [ModelA::class, ModelB::class]))
content: List<Object>
): PageImpl<Object>(content)
Then i annotated my Controller like this:
#Operation(
responses = [
ApiResponse(
responseCode = "200",
content = [Content(schema = Schema(implementation = PageModel::class))]
)
]
)
fun getPage(pageable: Pageable): Page<Object>
This generated this api response:
"PageModel": {
"properties": {
"content": {
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/ModelA"
},
{
"$ref": "#/components/schemas/ModelB"
}
],
"type": "object"
},
"type": "array"
},
... -> more page stuff from spring's PageImpl<>
And in the "responses" section for the api call:
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PageModel"
}
}
},
"description": "OK"
}
All generated openapi doc is similar to the autogenerated json when returning a Page, it just rewrites the "content" array property to have a specific type.

Adaptive Cards Templating in MS Teams

I can't seem to get this to work. If I send the following adaptive card payload to MS Teams:
{
"$schema" : "http://adaptivecards.io/schemas/adaptive-card.json",
"version" : "1.3",
"type" : "AdaptiveCard",
"body" : [ {
"type" : "Container",
"style" : "emphasis",
"items" : [ {
"type" : "Input.Text",
"value" : "${form.name}",
"id" : "name",
"label" : "Name"
} ]
} ],
"$data" : {
"form" : {
"name" : "geoff hurst"
},
}
}
I get a response in Teams like this:
I would have thought that the template should be expanded on the client-side, but this doesn't seem to happen. Have I misunderstood?
So in simple terms, Teams doesn't have an ability to render templates (basically that would mean taking the card template and the data payload and combining them together) - it can only accept the final version of the card.
As a result, if you're wanting to use templates, then you need to implement the data + template capability your side, to send the final card payload down to Teams. See here for examples on how to do this in js or dotnet. Truth be told, if you're in js (e.g. Node), Templating is not much more than string replacement, and if you're in dotnet (e.g. C#) there's a strongly-typed Adaptive Card library you might want to rather use anyway, in which case you're combining the "template" and the "data" already inside your code.
I think probably the best use of templating would be if you're receiving a template from some kind of "template repository", but I don't think there's really practically any such thing yet for Teams.
The method you are trying to use will not allow you to use dynamic data, I prefer you use data as a separate object and use Templating SDKs.
Please have a look at this sample on how to use template :
var templateJSON = File.ReadAllText(Path.Combine(".", "CardPath"));
AdaptiveCardTemplate template = new AdaptiveCardTemplate(templateJSON);
var memberData = new
{
userName = member.Name,
userUPN = member.UserPrincipalName,
userAAD = member.AadObjectId
};
string cardJSON = template.Expand(memberData);
var adaptiveCardAttachment = new Attachment
{
ContentType = "application/vnd.microsoft.card.adaptive",
Content = JsonConvert.DeserializeObject(cardJSON),
};
await turnContext.SendActivityAsync(MessageFactory.Attachment(adaptiveCardAttachment), cancellationToken);
In the above snippet as you can see, we need to create a model having the fields that we are using in the card.
In your case you need to create a object having the property as form -> name
var formData = new
{
form = new
{
name = "Testing"
}
};
after that use the expand method and the rest code would be same.

GraphQL: Explore API without a wildcard (*)?

I am new to GraphQL and I wonder how I can explore an API without a possible wildcard (*) (https://github.com/graphql/graphql-spec/issues/127).
I am currently setting up a headless Craft CMS with GraphQL and I don't really know how my data is nested.
Event with the REST API I have no chance of just getting all the data, because I have to setup all the endpoints and therefore I have to know all field names as well.
So how could I easily explore my CraftCMS data structure?
Thanks for any hints on this.
Cheers
merc
------ Edit -------
If I use #simonpedro s suggestion:
{
__schema {
types {
name
kind
fields {
name
}
}
}
}
I can see a lot of types (?)/fields (?)...
For example I see:
{
"name": "FlexibleContentTeaser",
"kind": "OBJECT",
"fields": [
{
"name": "id"
},
{
"name": "enabled"
},
{
"name": "teaserTitle"
},
{
"name": "text"
},
{
"name": "teaserLink"
},
{
"name": "teaserLinkConnection"
}
]
But now I would like to know how a teaserLink ist structured.
I somehow found out that the teaserLink (it is a field with the type Entries, where I can link to another page) has the properties url & title.
But how would I set up query to explore the properties available within teaserLink?
I tried all sorts of queries, but I am always confrontend with messages like this:
I would be really glad if somebody could give me another pointer how I can find out which properties I can actually query...
Thank you
As far as I'm concerned currently there is no graphql implementation with that capability. However, if what you want to do is to explore the "data structure", i.e, the schema, you should use schema instrospection, which was thought for that (explore the graphql schema). For example, a simple graphql instrospection query would be like this:
{
__schema {
types {
name
kind
fields {
name
}
}
}
}
References:
- https://graphql.org/learn/introspection/
UPDATE for edit:
What you want to do I think is the following:
Make a query like this
{
__schema {
types {
name
kind
fields {
name
type {
fields {
name
}
}
}
}
}
}
And then find the wished type field to grab more information (the fields) from it. Something like this (I don't know if this works, just an idea):
const typeFlexibleContentTeaser = data.__schema.types.find(t => t === "FlexibleContentTeaser")
const teaserLinkField = typeFlexibleContentTeaser.fields.find(f => f.name === "teaserLink")
const teaserLinkField = teaserLinkField.type.fields;
i.e, you have to transverse recursively through the type field.

How can I sort GeoJson file showing defined tags?

Good morning to all and thank you for your help.
I'm working in a map page (map.html) create by leaflet library that take data from a external geojson file called water_well.js. This file, previously generated by overpass service is just a list of markers. every Marker have some proprerties. Follow an exemple:
"properties": {
"operator:type": "international",
"is_in:district": "west_mamprusi",
"is_in:region": "northern",
"source:date": "2012-02-11",
"source:ele": "gps",
"water_wells:source_type": "borehole"
},
The main page extract those data from the file before with this javascript:
var wwMarker = L.geoJson(water_well, {
pointToLayer : function (feature, latlng) {
lat = feature.geometry.coordinates[0];
lng = feature.geometry.coordinates[1];
//following code that make error
op_type = feature.properties.operator_type;
district = feature.properties.is_in:district;
region = feature.properties.is_in:region;
source_date = feature.properties.source:date;
source_ele = feature.properties.source:ele;
source_type = feature.properties.water_wells:source_type;
.....
I'm sure the problem is my Zero javascript knowledge, but I'm not a programmer and I do this map for my NGO engaged in water wells in Burkina Faso.
The script for extraction of the data don't work in this point:
op_type = feature.properties.operator:type;
The problem is ":" because is invalid character.
The second question is that not all markers in the first file called water_well.js have the same "properties" filled ad actually it is possible that someone have different group of "properties like those two:
{
"type": "Feature",
"id": "node/1606958159",
"properties": {
"#id": "node/1606958159",
"amenity": "drinking_water",
"man_made": "water_well",
"name": "puits 4"
},
"geometry": {
"type": "Point",
"coordinates": [
-3.6235696,
12.02171
]
}
},
{
"type": "Feature",
"id": "node/1913126817",
"properties": {
"#id": "node/1913126817",
"ele": "170.8000030517578",
"grid_proximity": "grid_further_500_m",
"is_in:district": "builsa",
"is_in:region": "upper_east",
"man_made": "water_well",
"operational_status": "open",
"operator:type": "individual",
"pipe_connection": "no",
"pump": "manual",
"seasonal": "another_pattern",
"source": "MVP,Columbia University",
"source:date": "2012-02-14",
"source:ele": "gps",
"water_wells:source_type": "unprotected_well"
},
"geometry": {
"type": "Point",
"coordinates": [
-1.2430456,
10.3233693
]
}
},
maybe it is possible to extract all properties of each item independently from which one is present or not..... This can be de better way to solve the problem but I've no idea how to do that.
This is what I do (ckick the water tap to see pop-up): www.h2openmap.org/map
This is almost what I would like to do (ckick the water tap to see pop-up): overpass-turbo.eu/s/7Ov
Thank you for spending your time reading my question.
Have a nice day everyone, Francesco
You can access those properties using the bracketnotation, instead of using:
district = feature.properties.is_in:district;
Use bracketnotation:
district = feature.properties['is_in:district'];
Reference on property-accessors: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors
Now if you want to do something based on if a property exists there is a hasOwnProperty method available on objects. Since feature.properties is an object you can use that in a condition:
if (features.properties.hasOwnProperty('is_in:district')) {
// Property exists, do stuff
}
// or
if (!features.properties.hasOwnProperty('is_in:district')) {
// Property does not exist, do stuff
}
If you want to do something base on wether multiple properties exist you can use the && (and) operator:
if (features.properties.hasOwnProperty('is_in:district') &&
features.properties.hasOwnProperty('source:data')) {
// Properties exist, do stuff
}
// Or
if (!features.properties.hasOwnProperty('is_in:district') &&
!features.properties.hasOwnProperty('source:data')) {
// Properties do not exist, do stuff
}
You could use the || (or) operator to see if at least one of the conditions matches:
if (features.properties.hasOwnProperty('is_in:district') ||
features.properties.hasOwnProperty('source:data')) {
// At least one of the properties exist, do stuff
}
// Or
if (!features.properties.hasOwnProperty('is_in:district') ||
!features.properties.hasOwnProperty('source:data')) {
// At least one of the properties does not exist, do stuff
}
Reference for this can be found here under "Logical operators": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
You can use something like to build (or don't build) the data object that you need for your popup. Hope that helps.

Intel XDK : Parse.com integration "Unauthorized"

I am very new to Intel XDK and i try to make a very simple app like this in that video tutorial: Using Services Datafeed in App Designer.
But instead of the specific service from Rotten Tomatoes i want to integrate a database i have in Parse.com. For that i followed this video tutorial: "Integrating a New Service"
"[https]://software.intel.com/en-us/html5/videos/integrating-a-new-service",
and at the end the response was: "Unauthorized".
Then i found only this answer which comes from Intel's HTML5 Development Forums. I did not get anything either with this. The response was again: "Unauthorized".
And now i am confused and disappointed because:
I can't find other resources to help my self
I don't want to do it someone else instead of me, but
Without a full example, how is supposed to make it to learn?
My code now is similar with this in video: "Integrating a New Service"
In apiconfig.json
{
"MyService": {
"name": "The external service",
"description": "A great API with an external service",
"dashboardUrl": "https://parse.com",
"auth": "key",
"signature": "apiSecret"
}
}
In MyService.js
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
params['apiKey'] = credentials.apiKey;
url = url + '?' + $.param(params);
return $.ajax({url: url, type: 'GET'});
};
return exports;
})
And in MyService.json
{
"endpoints": [
{
"name": "classes",
"dashboardUrl": "https://parse.com/docs/rest",
"methods": [
{
"MethodName": "ServiceObject",
"Synopsis": "Show the entries",
"parameters": [
{
"Name": "objectId",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The object ID"
},
{
"Name": "text",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The text"
}
]
}
]
}
]
}
Can someone help me more? In whatever way he thinks best.
Thank you all
Edit:
After the following answer, my problem solved.
"MyService.js" file after the correction is:
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
};
return exports;
})
# user1736947: Your answer was concise and precise, exactly what i needed.
Certainly in the future I will need a lot of help, but for now I can go on my self-education thanks to you.
Thank you very much.
The way the authentication keys are accepted is different for different services. The example in the video.. rottentomatoes.. it accepted keys as a url parameter, so we append the key to the url and send it. However, seems like parse wants the keys in the headers (according to this)
So the equivalent ajax call will be something like :
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
This might not fix everything but it will move you a step beyond the authorization issue. Let me know if you are able to retreive the class this way.
To get a particular row entry, append the url with params.objectID.
Also, the XDK services tab has a parse-similar service ... kinvey. It also allows you to create a database online and retreive it.

Resources