I am working on a Spring 3 project and I need to format a Long field for Turkish currency. The default Locale of the application is en_US. I used the #NumberFormat annotation as below:
#NumberFormat(style=NumberFormat.Style.CURRENCY)
public Long getBudgetLimit() {
return budgetLimit;
}
The annotation works and formats the form field in English locale. However I need to use Turkish locale for this field. Is there a way to set the locale of a single field or a page different than the application's locale?
Edit: I just found the answer myself. Use a custom editor in the controller as below:
NumberFormat numberFormat = NumberFormat.getNumberInstance(new Locale("tr","TR"));
dataBinder.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class,numberFormat, true));
and do not use the #NumberFormat annotation. For same reason it gave an error for me.
There are many ways but you could for example register a custom implementation of AnnotationFormatterFactory<NumberFormat> as a bean which would allow you to handle the formatting manually. This is documentented in the Spring documentation section 6.6. The example in the documentation even handles the use case of adjusting #NumberFormat's behavior.
Related
Circumstances
I'm using Spring Boot with Thymeleaf for populating my HTML template files and get back the result as a String. For that I used SpringTemplateEngine.
The code looks like this
Context context = new Context();
context.setVariables(myProperties);
return templateEngine.process(htmlTemplateName, context);
The problem
For i18n I have a different approach. My thymeleaf HTML template namings are the following (similar to Freemaker templating):
templatename_default_FOO.html
templatename_en_EN_FOO.html
templatename_de_DE_FOO.html
templatename_default_ANOTHER.html
templatename_en_EN_ANOTHER.html
templatename_de_DE_ANOTHER.html
The convention is:
templatename - is the name of the template
default/en_EN/de_DE - is the locale which I get from an API - The locale may not exists in the templates, in this case I want to use the default template with the matching user parameter
FOO/ANOTHER - different parameter values which the users sets - they exists in atleast one template's name (the default should contain it)
Previously I used ResourceBundles to get the templates by locale if existed, otherwise the default value was automatically chosen. However with Thymeleaf implementation I don't know how to implement the same mechanics, because currently I get the template by providing the full name. If I add a locale which not exists I don't get back the default template.
Question
I know that i18n in Thymeleaf is done through language.properties, but in my case I would need a function where I provide the template name, the locale and the user parameter and I get back the specified HTML file if exists and if not the default HTML file with the matching user parameter.
Something similar:
public String getTemplate(Map<String, Object> myProperties, String templateName, Locale locale, String userParameter) {
Context context = new Context();
context.setVariables(myProperties);
return templateEngine.process(templateName, locale, userParameter context);
}
Is that possible somehow or I should use language.properties? Or I should write custom logic to check if the template not exists go with the default one?
Thanks in advance
I'm using the Varbox 2.x paid platform in one of my projects and I have a question regarding translatable models.
I have a News custom entity on which I've applied the HasTranslations trait in order to support title and content in multiple languages.
Everything works great and the admin crud also supports multi-language.
Also, in my frontend I've noticed that by accessing $news->title (just normal Laravel syntax) returns the value for the locale I'm currently on.
I was wondering if for example I could get the title in English, even if my locale is set to fr.
Thanks! Great work creating this package!
Yes, it is possible to get any attribute's value in any of the supported languages, regardless of your set locale, by using the getTranslation method.
$news = News::find($id);
$titleInEnglish = $news->getTranslation('title', 'en');
Here's the doc section for reference: https://varbox.io/docs/2.x/translatable-models#get-translation
Also, regarding what you've said that accessing $news->title returns the value for the locale you're currently set to, yes, that's true.
That's done inside the Varbox\Traits\HasTranslations trait, namely inside the getAttribute method (which actually uses the same getTranslation method, but with your set locale by default).
This is done to ease the implementation process, thus keeping it Laravel friendly :)
We are exposing swagger-ui from our webserver using the Swashbuckle package working on top of Asp.Net Core. We are hitting an input validation issue for our Guid input fields.
The GUIDs we are pasting in, which are read from other parts of the system, are formatted as deb83f8a3edc4b78a2ece3321f81b58b, note the missing dashes. The input validation rejects this as it expects dashes in the format (so it accepts deb83f8a-3edc-4b78-a2ec-e3321f81b58b).
The swagger document that we serve has the parameter as type: string and format: uuid. It calls to some internal validationGuid call that have a reg-ex that forces the dashes. From the browser Console it seems like it is looking for a component called JsonSchema_string_uuid but is not finding it.
So my question is how can I extend swagger-ui to override the validation of specific parameter type/formats?
UPDATE:
I was made aware of the RFC that specifies a UUID as containing dashes and a workaround. However, I'm still interested in learning about ways to customize the validation of both custom formats and specifically uuid?
While the OpenAPI Specification and JSON Schema do not currently define format: uuid, RFC 4122 defines UUID as containing dashes, and some comments in the OpenAPI repository suggest that format: uuid is supposed to follow RFC 4122. This means your example without dashes is most likely not format: uuid.
Consider replacing format: uuid with pattern: '^[A-Fa-f0-9]{32}$'.
What are the approaches to map i18n translated url paths?
For example lets say we talk about the follwing url (for locale en):
www.foo.tld/car/manufacturer
In german (de) this url would be
www.foo.tld/auto/hersteller
What i know about Controller RequestMapping i could use severel values to map these url's for one method like
#GetMapping(value={"/car/manufacturer/", "/auto/hersteller/"})
More seo optimized would be probably something with the current locale in the path like
#GetMapping(value={"/en/car/manufacturer/", "/de/auto/hersteller/"})
...but i dont want to start a discussion what would be the best uri seo wise.
This isn't so bad if to use only a few Locales/Languages but i would like to make this somehow dynamic.
Currently im using messages_xx.properties to map url path parts for generating urls in my application, like:
messages.properties
uri.car=car
uri.manufacturer=manufacturer
messages_de.properties
uri.car=auto
uri.manufacturer=hersteller
Im using them already for building links repecting the user locale which works fine.
What im searching now for is a elegant, less error prune way to map these urls in my controller. If i would change for example a value for the key uri.car and would have a static RequestMapping in my controller like in the example above i also need to change it there (if i dont forget!).
Also if i would like to add support for another language i would need to search in all controller and check if i need to add another value mapping.
Is there a smarter way how to map i18n path parts in Spring controllers, ideally respecting a request locale and resolve the path string with the help of messages_xx.properties?
Or would be a filter the way to go extracting path parts according to the requested locale and use internally only one language for mapping urls?
Supose that you have an EN message.properties and a DE message.properties with the following property:
url.car=/car/manufacturer/ in the EN
url.car=/auto/hersteller/ in the DE
In your #Controller you can get easily this properties configuring your messageSource and using it to get the properties:
Inject your configured MessageSource to allow Spring resolve the messages:
#Autowired
private MessageSource messageSource;
Then you can get all the properties from your message.properties file:
String url= messageSource.getMessage("url.car", put_here_your_locale);
Is it possible to have the Help Page sample generator ignore certain properties of a particular type?
For example, we use the same DTO for object Request and Response messages, for both POST and PUT requests. When user is POSTing a model (creating a new record) they don't need to provide the ID field.
But once its created and we serialize the new record into the response body, the ID field is included and returned to the client.
So in the POST request sample, I don't want the ID field to be displayed because for post request it doesn't make sense.
But the POST response sample, I do want the ID field displayed...
I am aware that there is the ApiExplorerSettings attribute which can be applied to a Class or Method...but is there anything similar for a Property?
Something like this would be great:
public class MyDTO
{
[ApiExplorerSettings(IgnoreForRequestApi = true, IgnoreForResponseApi = false)]
public int Id { get; set; }
// Other properties omitted for brevity...
}
Using the following annotation I've successfully hidden a property from the generation!
[ApiExplorerSettings(IgnoreApi = true)]
No, there isn't a similar option for a property. HelpPage uses formatter instances configured on the application to serialize the samples and as you can imagine the formatters must not have this knowledge within themselves.
Regarding workarounds:
a. You could explicitly set the raw sample for a particular action's requestsample via the SetSampleRequest extension of HttpRequestMessage. You should be able to see some examples about this in the file at *Areas\HelpPage\App_Start\HelpPageConfig.cs*.
b. In the file Areas\HelpPage\SampleGeneration\HelpPageSampleGenerator.cs, there is a method called WriteSampleObjectUsingFormatter which uses the application's formatter instances to write the samples. Here you would need to create new formatter instances having similar settings as your normal application has(so that they reflect the exact serialization/deserialization semantics that your application would normally react to when actual requests are made) and then try to hide the properties which you want to. We want to create new instances because we do not want to disturb the normal functioning of the application.
Example: In case of Json, you could create a new Json formatter instance and provide a ContractResolver which can hide the properties. Check this link: http://james.newtonking.com/projects/json/help/html/ConditionalProperties.htm
In case of Xml, I am not sure how we can hide properties without using the IgnoreDataMember attribute and also being non-intrusive.
Currently I would prefer option 'a' as its comparatively a simple workaround than 'b'.
ASP.NET WEB API uses Json.NET for JSON and DataContarctSerailizer for XML formatting so if you add [JsonIgnore] annotations over properties that you do not want included in your serialization should work just fine.