Qt lupdate and QTranslator group source strings into exclusive contexts. This means that a translation defined in one context will not be accessible within a different context.
The default context inside C++ is the name of a class that has overridden QObject::tr(). The default context inside declarative QML is the current filename without extension. To override the translation context, one would use qApp->translate( "context", "source" ) or qsTranslate( "context", "source" ) in C++ or QML.
I want to be able to use a single common translation context across a large project and I am finding that specifying the translation context with every single translation function is very tedious. Is there any existing or future Qt translation framework extensions that would simplify this task? I am looking for something that would be as simple as tr( "source" ) and qsTr( "source" ), but use a system-wide or project-wide default context. Any ideas?
You could use the Q_DECLARE_TR_FUNCTIONS() macro applied to a class definition that acts solely as a context:
class CONTEXT_CLASS {
Q_DECLARE_TR_FUNCTIONS(CONTEXT_CLASS)
};
where CONTEXT_CLASS could be as short as you'd like, let's say X (hoping that doesn't conflict with anything else in your code). That would make your tr() statements
X::tr("source");
Don't try to #define something to shorten X::tr, as that won't get picked up by the translation tool.
There's something easier than that. Use qtTrId/qsTrId (Qt/QML) instead of tr/qsTr and add the -idbased parameter to your lrelease calls. ID based translation has no context at all.
Related
I'm working on a big domain, for which maintainability is very important.
There are these general workers called ExcelHandlers that implement ExcelHandlerInterface (more on the interface in the ideas section) and basically get an UploadedFile as their input, upload them wherever they want and return the read data as an associative array. Now I have created this base class ExcelFileHandler which does all of these tasks for all excel files given two arguments:
1. The Directory to upload the file
2. the mapping of the excel columns to the indexes of the associative array.
Some ExcelHandlers might have to extend the ExcelFileHandler and do some more processing, in order to get the associative array of data.
The UploadedFile is always passed to the ExcelHandler from the controller.
Now here is the question. Given the generic structure of the ExcelFileHandler how should I define services for specific ExcelHandlers given that some only differ with the original one in the directory to upload the file and the mapping array.
My Ideas:
1. The first approach involves giving the directory and the mapping as the function arguments to ExcelHandleInterface::handle this will make the prototype something like handle(UploadedFile $file, array $mapping, $dir), $mapping and $dir are given to the function as arguments and passed to the handler by the controllers which has the parameters as constructor injections.
2.1 Defining the prototype of handle to be handle(UploadedFile $file), this would require the ExcelHandlers to have knowledge of $dir and $mapping. $dir will always be injected from the constructor.
2.1.1 Foreach individual ExcelHandler in the application, define a separate class e.g: UserExcelHandler, ProductExcelHandler, .... Which extend the ExcelFileHandler and leaves us again with two choices.
2.1.1.1 inject $mapping from outside. e.g:
// in the child class
public function __construct($dir, $mapping){
parent::__construct($dir, $mapping);
}
2.1.1.2 define $mapping in the constructor of the child class. e.g:
// in the child class
public function __construct($dir){
$mapping = array(0 => 'name', 1 => 'gender');
parent::__construct($dir, $mapping);
}
2.1.2 Not to create a class for each separate ExcelHandler and instead define the ExcelFileHandler as an abstract service and decorate with the right parameters to get the concrete ExcelHandler Service with the desired functionality, obviously ExcelHandlers with custom logic must be defined seperately, and to create a uniform code base, $mapping will always be injected from the Container in this case.
In your experience, what other paths can I take and which ones yield better results in the long term?
First of all, it seams as you've already put two separate things into one.
Uploading a file and reading it's contents are two separate concerns, which can change separately (like you said, $directory and $mapping can change case-by-case). Thus I would suggest to use separate services for uploading and reading the file.
See Single responsibility principle for more information.
Furthermore, due to very similar reasons, I would not recommend base classes at all - I'd prefer composition over inheritance.
Imagine that you have 2 methods in your base class: upload, which stores file to a local directory, and parse, which reads excel file and maps columns to some data structure.
If you need to store file in a remote storage (for example FTP), you need to override upload method. Let's call this service1.
If you need to parse file differently, for example combining data from 2 sheets, you need to override parse method. Let's call this service2.
If you need to override both of these methods, while still being able to get service1 and service2, you're stuck, as you'll need to copy-and-paste the code. There's no easy way to use already written functionality from (1) and (2).
In comparison, if you have interface with upload method and interface with parse method, you can inject those 2 separate services where you need them as you need them. You can mix any implementations of those already available. All of them are already tested and you do not need to write any code - just to configure the services.
One more thing to mention - there is absolutely no need to create (and name) classes by their usage. Name them by their behaviour. For example, if you have ExcelParser, which takes $mapping as an argument to a constructor, no need to call it UserExcelParser if the code itself has nothing to do with users. If you need to parse data from several sheets, just create SheetAwareExcelParser etc., not ProductExcelParser. This way you can reuse the code. Also correct naming lets understand the code more easily.
In practice, I've seen when function or class is named by it's usage, and then it's just used in another place with no renaming, refactoring etc. These cases are really not what you're looking for.
Service names (in another words concrete objects, not classes), can of course be named by their purpose. You just configure them with any required functionality (single vs separate sheets etc.)
To summarize, I would use 2.1.2 above all other of your given options. I would inject $dir and $mapping via DI in any case, as these do not change in runtime - these are configuration.
I am creating some Magnolia templates and would like to know if any one has found a way to create a #cms.newBar and somehow use a node as the list of available paragraphs. The syntax is as below:
[#cms.newBar newLabel="Add Content" paragraph="template1, template2" /]
I want to use the node instead to avoid having to come back and add new templates when they are created.
I have seen the docs here and know that nothing is specified but wanted to see if anyone had found a way?
You can do several things, all boiling down to the same:
configure a string property containing "template1, template2", in your template definition. Assuming you're using Freemarker as the templating language, refer to it with ${def.thatProperty} (def references your template definition)
have your model class return that value: ${model.whatsCooking}, where your model class has a method String getWhatsCooking() which returns "template1, template2" (or whatever else you could come up with that decides what paragraphs should be available
STK does something similar to (1) - its template definitions contains Lists of "available" paragraphs, and its templates use some utility method to turn that into a comma-separated list, use with the new bar, so something like ${stk.toStringList(def.main.paragraphs)} (I can't recall the exact names and semantics, but you get the gist).
You should perhaps consider looking into STK for that, and a whole lot of things.
As for documentation, perhaps the templating guide and other docs will be more useful than the javadoc/tlddoc in this case.
HTH,
1) We are using OpenEJB (both embedded and standalone) with a few deployed EJBs. We would like to specify some simple static business rules and values (example: icon_size=200). Normally, we would put them in a regular properties file (example: rules.properties). Since we shouldn't access the file system directly while inside the application server, is is possible to place those key-value pairs somewhere inside the ejb-jar.xml?
2) If not, is there a standard mechanism to do this? What is it?
Thanks
Use env-entry. In XML:
<env-entry>
<env-entry-name>icon_size</env-entry-name>
<env-entry-type>java.lang.Integer</env-entry-type>
<env-entry-value>200</env-entry-value>
</env-entry>
In annotation:
#Resource(name="icon_size")
int icon_size;
I personally just use a .properties file; well a TernarySearchTree which reads in .properties and .XML files and allows quick retrieval. These files are available at application level. However you can in EJB 3 inject env-entry elements into your EJB. This link explains it in good detail Injection of env entry
There are some OpenEJB extensions here that might be useful.
env-entries.properties
Check out the Custom Injection example which is basically allows the <env-entry> to be specified as plain properties in a META-INF/env-entries.properties file. Nice for collapsing all those name & value pairs into a simple properties file. Internally, we just generate the xml for you using those properties. The default type is always java.lang.String, which is good for this next part.
java.beans.PropertyEditor support
Any <env-entry> which is of <env-entry-type> java.lang.String will automatically have its type converted using the VM java.beans.PropertyEditor for the target type. That's also how Spring does the converting. There are few built-in converters, such as #Resource java.util.Date myDate and #Resource java.io.File myFile
I am relatively new to Flex/ActionScript, but I have been using a pattern of creating one file per function in my util package - with the name of the file being the same as the name of the function. Like if the file was convertTime.as:
package util{
public function convertTime(s:String):Date{
...
}
}
This way I can import the function readily by doing:
import util.convertTime;
...
convertTime(...);
I like this way better than importing a class object and then calling the static methods hanging off of it, like this:
import util.Util;
...
Util.convertTime(...);
But, the more I do this, the more files I'll end up with, and it also seems a bit wasteful/silly to put only one function into a file, especially when the function is small. Is there another alternative to this? Or are these two options the only ones I have?
Update: after some research, I've also posted my own answer below.
Yes, these are your two main options for utility libraries. We actually use both of these approaches for our generic utility functions. For a very small set of functions that we feel should actually be builtins (such as map()), we put one function per file, so that we can use the function directly.
For more obscure/specialized utility functions, we don't want to pollute our global namespace so we make them static functions on a utility class. This way, we're sure that when someone references ArrayUtils.intersect(), we know what library intersect() came from, and what roughly it's for (it intersects two arrays).
I would recommend going with the latter route as much as possible, unless you have a function that a) you use very frequently and b) is really obvious what it does at a glance.
I came across some other alternatives after all and thought I'd share them here.
Alternative 1 - use inheritence
This is probably an obvious answer, but is limited. You would put your static methods into a parent class, inherit them to get them in the subclasses. This would only work with classes. Also, because ActionScript is single inheritence, you can only inherit once.
Alternative 2 - Alias the methods
You still write utility functions as static methods hanging off util classes, but you alias them so you can access them with a shorter name, ex:
import mx.binding.utils.BindingUtils;
var bind:Function = BindingUtils.bindProperty;
Now you can just call
bind(...);
rather than than the lengthy
BindingUtils.bindProperty(...);
You can do this within the class scope and the function scope, but not the package scope - because apparently you can only have one visible attribute inside a package. If you do this in the class scope, you will want to make sure it doesn't conflict with your other class attribute names.
Alternative 3 - use include
As described in this flexonrails blog post you can use include to simulate a mixin in ActionScript. An include is different from an import in that all it's doing is copying the entirety of the file you are including from and paste it into the place you are including it at. So, it has completely no handling of namespace issues, you can not reference its full path name afterwards like you can with imports, if you have conflicting names, you are on your own with this. Also unlike import, it creates different copies of the same code. But what you can do with this is put any number of functions in a file, and include them into class or function scope in another file. Ex:
// util/time_utils.as
function convertTime(..){
...
}
function convertDate(..){
...
}
To include:
include 'util/time_util.as'; // this is always a relative path
...
convertTime(...);
# an0nym0usc0ward
OOP is simply the method of consolidating like functions or properties into an object that can be imported and used. It is nothing more that a form of organization for your code, ALL code executes procedurally in the processor in the end, OOP is just organization of sources. What he is doing here may not be OOP as you learn from a book, but it does the exact same thing in the end, and should be treated with the same respect.
Anyone that truly understands OOP wouldn't be naive enough to think that the approved and documented form of OOP is the only possible way to object orient your code.
EDIT: This was supposed to be a comment response to an0nym0usc0ward's rude comment telling him to learn OOP. But I guess I typed it in the wrong box :)
I'm re-writing an MXML item renderer in pure AS. A problem I can't seem to get past is how to have each item renderer react to a change on a static property on the item renderer class. In the MXML version, I have the following binding set up on the item renderer:
instanceProperty={callInstanceFunction(ItemRenderer.staticProperty)}
What would be the equivalent way of setting this up in AS (using BindingUtils, I assume)?
UPDATE:
So I thought the following wasn't working, but it appears as if Flex is suppressing errors thrown in the instanceFunction, making it appear as if the binding itself is bad.
BindingUtils.bindSetter(instanceFunction, ItemRenderer, "staticProperty");
However, when instanceFunction is called, already initialized variables on the given instance are all null, which was the cause of the errors referenced above. Any ideas why this is?
You have 2 options that I am aware of:
Option 1
You can dig into the code that the flex compiler builds based on your MXML to see how it handles binding to static properties. There is a compiler directive called -keep-generated-actionscript that will cause generated files to stick around. Sleuthing through these can give you an idea what happens. This option will involve instantiating Binding objects and StaticPropertyWatcher objects.
Option 2
There is staticEventDispatcher object that gets added at build time to classes containing static variables see this post http://thecomcor.blogspot.com/2008/07/adobe-flex-undocumented-buildin.html. According to the post, this object only gets added based on the presence of static variables and not getter functions.
Example of Option 2
Say we have a class named MyClassContainingStaticVariable with a static variable named MyStaticVariable and another variable someobject.somearrayproperty that we want to get updated whenever MyStaticVariable changes.
Class(MyClassContainingStaticVariable).staticEventDispatcher.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE,
function(event:PropertyChangeEvent):void
{
if(event.property == "MyStaticVariable")
{
someobject.somearrayproperty = event.newValue as Array;
}
});
I think you need to respond to the "PropertyChanged" event.
If you're going to do that, use a singleton instead of static. I don't think it will work on a static. (If you have to do it that way at all, there are probably a couple ways you could reapproach this that would be better).
var instance:ItemRenderer = ItemRenderer.getInstance();
BindingUtils.bindProperty(this, "myProperty", instance, "theirProperty");
After fiddling with this for a while, I have concluded that this currently isn't possible in ActionScript, not even with bindSetter. It seems there are some MXML-only features of data bindings judging by the following excerpt from the Adobe docs (though isn't it all compiled to AS code anyways)?
You cannot include functions or array
elements in property chains in a data
binding expression defined by the
bindProperty() or bindSetter() method.
For more information on property
chains, see Working with bindable
property chains.
Source: http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_7.html
You can create a HostProxy class to stand in for the funciton call. Sort of like a HostFunctionProxy class which extends from proxy, and has a getProperty("functionInvokeStringWithParameters") which will invoke the function remotely from the host, and dispatch a "change" event to trigger the binding in typical [Bindable("change")] Proxy class.
You than let the HostProxy class act as the host, and use the property to remotely trigger the function call. Of course, it'd be cooler to have some TypeHelperUtil to allow converting raw string values to serialized type values at runtime for method parameters (splitted by commas usually).
Example:
eg.
var standInHost:Object = new HostFunctionProxy(someModelClassWithMethod, "theMethodToCall(20,11)");
// With BindingUtils.....
// bind host: standInHost
// bind property: "theMethodToCall(20,11)"
Of course, you nee to create such a utlity to help support such functionality beyond the basic Flex prescription. It seems many of such (more advanced) Flex bindings are usually done at compile time, but now you have to create code to do this at runtime in a completely cross-platform Actionscript manner without relying on the Flex framework.