What is the correct way to specify DC metadata for a multi-language ePub? - metadata

I am developing an ePub. In the content.opf file I have to specify a series of metadata by using DC standard. For example dc:title and dc:creator.
However my book is a multilanguage book, that is, it contains two translations of the same text: English and Russian. The standard reference manual states that I can have more dc:language statements. For example:
<dc:language>en</dc:language>
<dc:language>ru</dc:language>
but it does not say how to specify the other metadata for more than one language. Consider, for example, dc:creator. I tried
<dc:creator xml:lang="en">Dario de Judicibus</dc:creator>
<dc:creator xml:lang="ru">Дарио де Юдицибус</dc:creator>
I get an error from the distribution platform validator, which states that the format of ePub is not correct. It looks like I cannot use xml:lang in dc:creator even if, in theory, that is an XML attribute that can be used with any XML tag. Same for dc:title:
<dc:title xml:lang="en">My Book Title</dc:title>
<dc:title xml:lang="ru">Название Mоей Kниги</dc:title>
Could someone who has had to face the same problem as me, namely writing the OPF for an ePub that contains a text in multiple languages, tell me what is the correct way to do it? In the standards for the OPF 3.x I have not been able to find any useful information to establish this.
SOLVED
I verified my code with one of the author of the W3C specifications for OPF and he told me that what I wrote is correct, but that some validator is not used to multi-language documents, so that the problem is the validator, not the code. I write this in case someone else may have the same problem.

Related

keep/copy XMP with libexif

I try to add a thumbnail to a JPEG picture using libexif.
For now I'm borrowing the code from exif (the command line tool that is shipped by the libexif team).
However I noticed the XMP tags get deleted from the metadata. There is an old bugreport here.
I tried to see how to achieve this anyway with libexif but I don't really understand how to get the XMP from input file and put it in the output file. I just want to copy all XMP data, I don't need to extract anything of it.
I saw there is a TAG EXIF_TAG_XML_PACKET in exif_tag.h but couldn't figure out how to read/write this tag.
A related solution is in this SO answer but it looks complicated. I'm not familiar coding in C.
Is it actually possible to keep all XMP when using only libexif API? Have things changed in recent years on that? How would you write this in code?
Thanks
I believe it should be somewhat straightforward. XMP fields are described in the ISO/Adobe standard. Regular Kotlin/Java/Android file I/O and some string manipulation should be all that is required.
I would start out by becoming intimately familiar with ISO 16684-1:2019. Then, write a method for your jpeg file class that grabs all the XMP fields. Store those fields in a temp file (to prevent difficult to recover data loss in the event of your code or libexif crashing). Hand the file off to libexif. Generate the thumbnail. Finally, when that's done you can restore the XMP fields. If the thumbnail is stored in an XMP field as well (and it sounds like it is), it may be easier to concatenate that field with the other ones which were already grabbed, updating the temp file so that it contains EVERY XMP field, before adding all of the XMP fields back to the jpeg.
Unfortunately, I do not currently have the time to read a 50 page ISO standard, synthesize the information, and then write the code to implement the solution. Here's a link to the standard at least, to get you started.
https://www.iso.org/obp/ui/#iso:std:iso:16684:-1:ed-2:v1:en

Adding signingCertificateV2 attribute to SignedCms

ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.5"), Encoding.UTF8.GetBytes(str.ToString()));
SignedCms signedCms = new SignedCms(content, true);
CmsSigner cmsSigner = new CmsSigner(cert);
cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;
cmsSigner.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
cmsSigner.SignerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber;
Pkcs9AttributeObject att = new Pkcs9AttributeObject();
AsnEncodedData data = new AsnEncodedData(new SHA1Managed().ComputeHash(cert.RawData));
cmsSigner.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.UtcNow));
//cmsSigner.SignedAttributes.Add(new Pkcs9ContentType());
//cmsSigner.SignedAttributes.Add(new Pkcs9MessageDigest());
signedCms.ComputeSignature(cmsSigner);
return Convert.ToBase64String(signedCms.Encode());
I have used this code to sign a document and this code is working fine but my problem is that there is another requirement needed to add "SigningCertificateV2" attribute as a signed attribute...
I have already added ContentType, MessageDigest and SigningTime. But i dont know how to add "SigningCertificateV2" attribute.. (1.2.840.113549.1.9.16.2.47)
Can You please help me with this?
(It seems this question's been sitting unanswered for more than a year and a half, so I really hope Asharf managed to comply with the new requirement somehow. There's been more than 300 views though, so hopefully a late answer would still be helpful.)
The types in System.Security.Cryptography.Pkcs do not provide support for the full range of attributes defined by various Cryptographic Message Syntax (CMS) specs like CMS Advanced Electronic Signatures (CAdES) and Enhanced Security Services Update (ESSCertIdUpdate), but only for the most commonly used attribs like Pkcs9ContentType, Pkcs9MessageDigest, Pkcs9SigningTime, etc.
Specifically, there's no "strongly-typed" wrapper around the SigningCertificatev2 attribute, defined by ESSCertIdUpdate (RFC 5035). In that case, one has to use the "generic" CryptographicAttributeObject type and construct the ASN.1 encoded data for the attribute "by hand", that is, concoct a raw byte[], typically by using System.Formats.Asn1.AsnWriter (and thoroughly reading the relevant RFC -- that's always a good idea, btw).
Defining a wrapper for the SigningCertificatev2 attrib requires a fair amount of code as several other related RFC types like ESSCertIDv2 and PolicyInformation need also be defined.
Luckily, there's a well-known open-source software project that already does exactly that -- it can be used for "inspiration" ;-). That's NuGet, and specifically the NuGet client.
(I know link-only answers are frowned upon on SO, but I guess a link-mostly answer is better than no answer, so here goes...).
Here are the links to the relevant parts in the GutHub repo.
CreateSigningCertificateV2() in AttributeUtility
The SigningCertificateV2 type itself.
The EssCertIdV2 type, used by SigningCertificateV2.
The NuGet client's attribute implementation can't be used directly as a library, but it should provide a nice guideline about how to construct the PKCS attribute.

Custom Search Results in REST MarkLogic

So new to MarkLogic am stuck and not finding the documentation of use. I know what i need to do, just do not know how to do it.
I have a keyvalue? search on my REST server which returns ML's standard search results and XML snippet. I want to create my own custom search result which will output a title element for my XML files.
I am aware that i need to create an XSLT transformation document and upload that to the server but do not know how to target ML's search function or how to write this out.
I have basic knowledge of XSLT, if i just created something that targets each files title using xPath will this work, or does ML require use of their custom functions?
I know its a bit broad, but hopefully someone can point steer me.
Sounds like you are talking about the GET /v1/keyvalue endpoint of MarkLogic REST API. Unfortunately that does not allow you to choose a transform. You can probably use GET /v1/search with a transform param instead though, using a structured query for an element value query. The docs contain a good syntax reference on that.
Docs on creating and managing transforms can be found here:
http://docs.marklogic.com/guide/rest-dev/transforms#chapter
HTH!
You can use extract-metadata in your search options with search:search or the /v1/search/ REST API endpoint to include the title element in a metadata element or JSON property in your results:
import module namespace search = "http://marklogic.com/appservices/search"
at "/MarkLogic/appservices/search/search.xqy";
search:search(
"my query string",
<options xmlns="http://marklogic.com/appservices/search">
<extract-metadata>
<qname elem-ns="" elem-name="title"/>
</extract-metadata>
</options>)
If you need more flexibility, you specify a custom snippet implementation or a results decorator function in your search options.
Is this key-value or full text? For key-value you could use XPath. Any XPath that starts with / or // or fn:collection() or fn:doc() will search the entire database. You can search specific document(s) or collection(s) too.
For full text you'd probably want to use https://docs.marklogic.com/search:search - or possibly https://docs.marklogic.com/cts:search for really low-level control.
There's some example code using search:search from XSL at https://github.com/marklogic/RunDMC which might help. It doesn't use the REST API: it's a traditional form-submit web page. But the view/search.xsl code might give you some idea how to call the search API from XSLT.
That RunDMC code might also help you if you need to call XSL from XQuery: take a look at controller/transform.xqy.

GWT i18n - Plural Forms doesn't work at all?

I'm using GWT internationalization Messages. The documentation for Plural Forms says this should work:
#DefaultMessage("{0} {1,number} hours {2}")
#PluralText({"one", "an hour"})
String hours(String prefix, #PluralCount int count, String suffix);
Well, it doesn't. Whatever value of count it still delivers DefaultMessage (e.g. "1 hours ago"). Same if I use a .properties file:
hours[one]=an hour
hours[few]=some hours
hours={0} {1,number} hours {2}
Is there a bug in the docs or in GWT (I'm using GWT 2.0.3) or in me? If any of the two former, anyone knows of a workaround?
EDIT: More clues to this mystery. I can get plural handling to work if I don't rely on default locale handling. That is, I need:
In my module's gwt.xml file:
<extend-property name="locale" values="en"/>
In my Messages extentsion:
#DefaultLocale("en")
public interface MyMessages extends Messages { ...
Explicitly load the "en" locale by appending to the URL
&locale=en
See http://groups.google.com/group/google-web-toolkit/browse_thread/thread/80ae300213cc6adb where I have cross posted this question.
EDIT 2: The reason I entered this GWT plurals land is that I'm creating a "GWT HUman Readable Relative Timestamps" module. Open sourced at GitHub: http://github.com/PEZ/GWT-Relative-Time Please check it out. It'll very soon have correct singular forms and support for some languages. =)
Also I think it will save people time to know that the default English plural rule only supports "other" and "one".
DefaultRule_en.java uses DefaultRule_1_0n.java
So you have to redefine DefaultRule_en.java if you want to use "none","two",few"...
You can see the available rules in the package com.google.gwt.i18n.client.impl.plurals.
Getting used to answering my own questions =) Here's cross post of my "answer" on the GWT Google group:
There seems to be a bug with the default locale handling. Here's how I have reached that conclusion:
I wanted to add some locales to my module. Figured I could get a boiler plate for the properties file if I used the #Generate annotation. I noticed that it created both an _en.properties file and a _default.properties. What's more; the _en file completely lacked the plural form info! The _default file had them though.
I then moved the _defaults file to the same directory as my TimeMessages.java file and renamed it TimeMessages_default.properties.
With this in place I can remove <extend-property name="locale" values="en"/> from my module's .gwt.xml file and, more important, the &locale=en from the URL when running my app. I still need the #DefaultLocale("en") annotation though, even though the documentation clearly states that this is not necessary.
In conclusion, if you run into this problem, try:
generating properties files using #Generate
place YourMessages_default.properties side by side with YourMessages.java
prepend the YourMessages interface with a #DefaultLocale("en") annotation.
About that #Generate. This is what worked for me. Just before my extension of the Message interface:
#Generate(format = {"com.google.gwt.i18n.rebind.format.PropertiesFormat"})
The GWT log said it created my properties file, but I couldn't find it. I fixed that by adding the compiler flag -extra extras and then found the properties files generated in the extras directory. Including this info here since I spent more than an hour figuring it out.
Another solution from the gwt issue list here:
You have to define the #DefaultLocale in the MyMessages.java:
#DefaultLocale("en")
public interface MyMessages extends Messages {
public String items(#PluralCount #Optional int count);
}
and in MyMessages.properties:
items={0} items
items[one]=one item
One more thing I found is that you can define a fallback locale like this:
<set-property-fallback name="locale" value="en"/> in your module XML file

Query with toLocalizedTime in Plone

I'm using toLocalizedTime to output a date, as below
<span tal:content="python:here.toLocalisedTime(date.get('start_date'))"/>
This outputs eg. 2007/08/02, I'm just curious as to how one would alter the output so that it reads 02/08/2007
I'm not having much luck finding much info on toLocalizedTime, would someone point me in the right direction?
This depends on whether you have English selected as the site language (Site Setup >> Language). If so, then the default settings are used. You can change the defaults by dropping down into the ZMI, then into 'portal_properties', then 'site_properties'. The fields to change are either 'localTimeFormat' or 'localLongTimeFormat' depending on whether you pass in 'long_format=1' to the toLocalisedTime function.
If on the other hand, you have translations set up, the format may instead be pulled from the translation file for the locale selected. I'm not sure what is the easy way to change the format in this case (other than switching the site back to English). I guess you can register your own translation file but I've never needed to do that so you're going to have to look up the details.
Date string formatting follows the Python rules (http://docs.python.org/library/time.html#time.strftime).
Perhaps even more detail than you need:
here.toLocalizedTime()
is defined in the plone browser view at...
CMFPlone/browser/ploneview.py
which looks up the 'translation_service' utility, to call its 'ulocalized_time' function, defined at...
CMFPlone/TranslationServiceTool.py
which itself calls the 'ulocalized_time' function defined at...
CMFPlone/i18nl10n.py
As always, you can learn interesting things by grepping the source code ;-)
For an up to date answer for Plone 4.3 (after going through the source code)
These fields are now in the registry found at:
http://localhost:8080/yoursite/portal_registry
Then filter on "i18nl10n", which should give you the 4 fields you need to change.