We maintain an ASP web app, which has a publicly visible interface that has to be localised into a large number of languages, and a private interface that still needs localisation, but only into a subset of the languages.
As much as possible, when we localise we put them into different resource files according to whether the string could appear on the public interface, or only the private one. However, inevitably mistakes are made, and I'd like to find ways to find resources that have been classified incorrectly. There's a lot of code shared between them, so the assembly that some code is in is not sufficient to determine this.
One way of doing this would be to record the resource name & location of every resource that gets accessed via the public interface, which allows us to (a) detect any that have been misclassified as private, and (b) investigate any that have been categorised as public but don't appear in this list. It looks like this might be possible by providing custom resource providers that wrap the default ones but record resource keys.
An alternative, but potentially more useful, option would be to record when a resource couldn't be found in a specific culture, and the system has had to fall back to the invariant culture resource. This will help us track down any untranslated messages. However, I'm struggling to find a way to do this.
Are there any good solutions here to avoid me writing my own? How do others manage similar scenarios? We'd rather avoid the cost of unnecessarily translating strings that can only be seen in the private interface into languages that it's not supported for.
In the interest of full disclosure, I'm the (sole) author of a commercial localization program for Visual Studio. I therefore stand to profit if you decide to research and purchase it. I'm not here to sell you a copy of it though (I don't work that way). I'm trying to legitimately help you and my program may be able to (though it's still unclear to me at this stage). You'ld also have to be open to a paid solution of course, assuming you can't find a better way. If I knew of a way for free I'd post it here. In fact, if my app didn't take so long to originally develop I would have given it away for free. I suggest you download the evaluation copy at http://hexadigm.com/FreeDownLoads.aspx (developer's version) to get an idea of what it can do (and ideally read about it on the site first). The evaluation version can only translate 10% of your strings however so it may be unwieldy to properly test what you're after. The program may have potential ways to deal with your situation though, if I understand it correctly, but it remains to be seen (for instance, you could bundle your public and private strings into separate ".trn" files, which you'll learn about if you research the app, but you obviously need to identify these strings first of course - how my app can help in that regard is still unclear). The upshot is you'll need to get a basic understanding of the program first though. It may be better to contact me offline at support#hexadigm.com. I don't believe any further discussion here will benefit other users but if the moderators feel otherwise then they can weigh in (I'd be happy to discuss it here if they wish, since the app does address various localization deficiencies in Visual Studio, but I don't want to violate the site's rules - I'm not here to promote the app so I won't discuss any specifics without their approval).
Related
Most questions of this type are seeking to alter the program behavior (things that could be decided at run time) or want to deal directly with debug printing. This is a bit different.
I have code that depends on a peripheral (like a card reader). Sometimes I don't use it, which means the library isn't present. (And I'm being nice, because "library" turns out to mean installing a 2GB software suite). When I remove the library, I can't open the device. If I can't open the device, I can't create the class member that uses it. With the class inoperative, I can't call its methods from within the code. Therefore, I can't just choose not to execute it; I need it to go away since it will not compile without the library.
Preprocessor directives like #if and all that are ok, maybe; but these things appear in more than one file, which means independently maintaining a #define at the top of each. I come from a simpler place (meaning, C) where one header file can be used to control this. I note that C# is rather hostile about #define (either the label exists, or not; no constants or calculations allowed), and that makes me think there's another way.
How do you handle this?
---Follow-up(s)---
I did read the "duplicate" Q/A's, and have a fairly good picture of what I'm dealing with. I didn't find those questions in my original search, but sometimes that's just how it is.
#Amy suggests that #define at the top is "not how it's done" but rather "put it on the command line". So, (if I realize we are sticking with this mechanism) the discussion might go to examining ways to have that happen . One does not simply drop to a terminal and do that. It happens as "IDE features" or "IDE hacks".
#Alexei Levenkov asks what I really want. I really want to (a) not get compile errors, and (b) do it by selectively leaving out the code. And, find the C# equivalent to the way I proposed.
Some more constraints are addressed by the fact that I haven't been using VS or C# for all that long. So I know a lot less than you all do. Considering I got the code from the last person and have to deal with what I see, I don't want to set up the person after me to have to figure out what "interesting" thing I might have done to make it work. Thus, things like hand-editing a project file may work but will also cause consternation down the line.
# Eric Lippert suggests "hostile" is really "sensible". I may have had my tongue too far into my cheek on that one. VS seems to be telling me I'm doing it wrong, so I sensed there's a "right way" I simply don't know about. As for the 2GB supporting application, I will go to various computers and pull down the repository and try out something, and so this "overhead" wants to propagate with it. It's worse if I'm linked through my phone to do the download. And if I build the application with everything included, the end user is then required to install that software suite before the program will run. In theory, they could be required to buy the software. If I sent you a tic-tac-toe game, and told you it wouldn't run until you installed Oracle, you'd probably pass on the whole thing.
I considered the "stub out the interface" idea, but there seemed to be more hooks into the class than I wanted to deal with. Plus, I don't know what these things do, so I have to know something about them in order to "fake" them.
In the end I decided that we're still largely using the #if scheme to get this done, and the replacement feature I imagined might exist, doesn't. And I'm using the provision in the project file(s) as cited by #Jim G. as it gets the job done and is only a little imperfect. It's good enough.
As #BJ Safdie said here:
Set them in your Compilation Properties or Build options.
You get to the build options by right-clicking the project and selecting
properties from the menu.
Having rather large project using Resources for internationalization (following this guide: ASP.NET MVC 2 Localization complete guide, using things like data attributes, and so on) we run into the need of translating the resource files. In the beggining of project I selected approach to have lot of small resource files - for each view, viewmodel, controller, ... So I ended up having hundreds of resources. During the translations (which is done by our partners using ResXManager tool we run into trouble identifying the context of the string (where is it displayed, to find out the correct form of translation to make sense when displayed).
So I was asked to make the mutation of application which do not display the localized values, but the keys (or string names). E.g. having string in resources TBL_NAME used somewhere in the view like #ResX.TBL_NAME and translated into english as "Name", I would like to show it in this special mutation as "TBL_NAME", so the translator may see the context - where exactly this string is used.
The best would be, if this is not special build of application, but rather the another "language" of the application available for translators, so he can switch between english and this "unlocalized" languages.
I'm looking some easy ideas of doing this. So far I was thinking of these approaches:
Override ResourceManager.GetString - cannot use, because we use generated Designer classes to access strings massively and so far I haven't find a way to change created ResourceManager (see this answer). Did I miss something?
Create resources for some unused language, which will contain pairs string name/translated value as TBL_NAME/TBL_NAME - viable, but very exhausting since we have hundreds of resources. Also the addition of new resource will require us to remeber that we need to add also this unused language resource will exact same strings name. You also have to do twice much work when adding single string to application.
At the moment, it seems for me, that using resources and current approach it is impossible to solve this task, so I decided to ask this as question (and I'm aware it is rather discussion than question) here, hoping, someone will give me some hint about other approach to solve this problem.
My preferred option would be to give the translators an environment where they can see what they are translating. Rigi requires a bit of setup (basically you need to add an additional UI language), but once you have done that translators can work within the live website - or in a test instance, which is what we did.
They can also work in screenshots, which is convenient when translators would have to access admin or other role specific pages but you do not want to bother giving them all kinds of user rights. These screenshots can be generated as part of automated UI tests or during manual UI testing.
I am afraid I can't say anything about the cost of the solution, but our translators are really happy with it. I am not sure if this is what you are looking for since you asked for an easy solution, but it definitely solves the issue of giving translators the context they need to do their job - better than displaying resource IDs.
I'm working on a website that will deployed internationally. Very big site, but for the sake of simplicity, all we're concerned about is my Error.aspx with c# code behind. I'd like to make this custom error page as dynamic as possible. There's at least a handful of languages we need to read this page in right now, and more to come. This page needs to work independently and without a database to reference.
I'd like to have some text, and have the appropriate translation appear based on the language appropriate for that domain... e.g. ".com" = English, ".ca/fr" = French, ".mx" = Spanish... you get the idea.
What's the best way to do this?
I've looked into API's, but the decent ones have a cost threshold, and while it might look really helpful, this is just pretty standard error message text, that's unlikely to change, so that seems like overkill to have a dynamic translator. It might help with scalability, but it's extra money indefinitely, when it will only save vs hard-coding on the handful of occasions where we add another language/country/domain.
The other idea I had was to simply hardcode it in the c#. parse out Request.URL and get the domain, and make a ever-growing switch statement which would assign the appropriate text. (As an aside, I'm also trying to find a better way to do this, but is the country code something that would be an available piece of information from either the request object or server?) This way would be independent, precise, and the only drawback on a concrete level would be the cost of adding new languages, or changing every string (probably not that many, at least at first) if the content of the error message needed to be adjusted. But this feels like bad practice.
I've been researching this for a day now, but I haven't found any alternatives to these 2 options. What are the best practices for handling small amounts of text for translation, without the use of a CMS?
There is an easy built-in way to handle localization in ASP.NET Web Forms. It uses the Language Preference settings in the client's browser to select the language. Posting the steps of setting it up would be redundant since there's lots of information on this subject available online. Here is a good tutorial.
EDIT:
It might be a good idea to read up on HTML resource files. That is the HTML standard for handling different languages (referred to as localization). And it is what ASP.NET uses in the background when creating a local resource for a server control.
I just recently found out here that it is possible (at least in c#) to look up private fields and properties due to reflection.
I was surprised, although I knew that somehow constructs like the DataContractSerializer class need the possibility to access them.
The question now is, if anyone can access every field in my classes, this is kind of insecure, isn't it? I mean what if someone has a private bool _isLicensed field. It could be changed easily!
Later I found out here that the field accessors are not meant as a security mechanism.
So how do I make my Application safe, meaning how do I prevent anyone other than me from changing essential status values inside my classes?
The question now is, if anyone can access every field in my classes, this is kind of insecure, isn't it?
Not everyone can. Only code with sufficient permissions - trusted code. Untrusted code is restricted quite a bit. On the other hand, if the person who wants to use reflection has your assembly, they can run trusted code on their own machine. That's not a new attack vector though, as if they've got your code they could also modify it to make the field public in the first place.
Basically, if code is running on their machine, you should expect them to be able to do pretty much anything with it. Don't rely on access modifiers to keep anything secret.
So how do I make my Application safe, meaning how do I prevent anyone other than me from changing essential status values inside my classes?
If the hostile user is running your code themselves, you pretty much can't. You can make it harder for them, but that's an arms race which is no fun.
So one option in some cases is not to let anyone else run your code - host it on the web in an environment you've locked down. That's not appropriate in all cases, of course.
If you have to let users run the code themselves, you need to weigh up the downsides of them tampering with the costs of making that tampering difficult. We can't really help you with that balancing act - we don't have any idea what your application is, or what the costs involved are (reputational, financial etc).
private public and so on are a part of http://en.wikipedia.org/wiki/Encapsulation. the use is to make your API clear and to avoid mistakes.
there is no solid way to avoid people messing with your program.
you may have noticed that all programs are cracked in a few days usually.
in .net it is VERY easy because of IL code been very readable http://ilspy.net/ and such allow you to take any DLL and just read it like C# code.
you can make it more annoying to read your code using obfuscator
http://en.wikipedia.org/wiki/List_of_obfuscators_for_.NET
but applications like http://de4dot.com/
break this VERY easily.
SecureString is a nice trick: https://msdn.microsoft.com/en-us/library/system.security.securestring%28v=vs.110%29.aspx
writing your code in low level language like c++ might make cracking your code really annoying. but soon a skilled hacker will do whatever he wants with your program.
the only option that might be safe is providing your application as a cloud service where the user only sees the screen output and sends keyboard/mouse input.
This was meant to be a comment for John Skeets answer but ran out of room..
Great answer by the way, but I also must add that code is not meant to be secure its meant to clearly defined.
Most developers know how to change classes and inject into classes. There are many utilities to not only decompile your code but to also allow injection into it.
I wouldn't spend to much effort trying to your make code more secure, I would try and expect the code to be changed. Many programming languages do not have such modifiers as private, public, internal, protected etc. They rely on the developers to understand the consequences of using this code on their own. These programming languages have been quite successful as the developers understand that modifying, calling or injecting into code the API does not specify has results that the developing company cant and will not support.
Therefore, expect your code to be modified and ensure your applications responds to invalid changes appropriately.
Sorry if this seems like a comment...
To add to all the other answers, a simple way of looking at it is this: If the user really wants to break your code, let them. You don't have to support that usage.
Just don't use access modifiers for security. Everything else is user experience.
I'm trying to think of a way that prevents others from using your published dlls. For example let's say you create a cool lightweight WinUI photo processing tool that's separated into several assemblies. One of them is your precious filters.dll assembly that basically does all of the core filtering work. Once you publish your application, how can you prevent others from taking this filters.dll and using it in other projects?
I've already tried to look at the StrongNameIdentityPermissionAttribute which has a good example here but it doesn't seem to work for me, the code just works without throwing any security exceptions..
Any ideas?
Strong names have nothing to do with preventing or inhibiting reverse engineering. They only serve to stop people substituting assemblies with hacked versions - and only if people havent turned off strong name verification. There's nothing to stop people taking your code, ILDASMing or Reflectoring and re-ILASMing as they see fit.
InternalsVisibleTo and friends are on an honour system at the compiler level too, so not much use for what you're looking for (although for some obfuscators, internals get more agressively obfuscated than publics by default - though this can generally be overcome). My main concern here is to point out that jsut because something is 'internal' doesnt bestow on it any magic code protection pixie dust that stops reverse engineering.
Most of this stuff re why these sort of approaches arent a solution for code protection is summarised very well in this article
There are also code protection products on the market that go beyond obfuscation which sound like the tool for the job you describe.
One method that may work for you is to declare the the methods and classes in the filter assembly to be internal and explicitly specify the assemblies that can access it as "friends".
You do this with an assembly declaration (ususally in assemblyinfo) like:
[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]
see Friend Assemblies for more info.
Also make sure you obfuscate the assembly or people can dig into the code with reflector.
Don't bother worrying too much about protecting your .NET code. If you deploy it to someone elses computer, and that person wants to use or read your code, they will.
If your code is valuable enough you need to keep it on a computer you control (such as a web server) and guard against unauthorised access.
Obfuscation will only slow determined people down. Strong naming and signing is not used to protect your code, but instead to ensure that the user can confirm the code originates from who they expect it to come from (ie ensure it hasn't been tampered with).