diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2012-02-15 13:13:20 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2012-02-15 13:13:25 +0000 |
commit | d5b804be02bace138f87272b290ab794e2789a21 (patch) | |
tree | f99208052cf312384b6b206480d55240b764225d | |
parent | 73e6e3f5d45247a9b5891c95ce05c9b195afaeb4 (diff) | |
parent | aa64fd15879e30d307aeb360b014ef1338bb11da (diff) |
Merge branch 'captcha'
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: Dario Freddi <dario.freddi@collabora.com>
-rw-r--r-- | spec/Channel_Interface_Captcha_Authentication.xml | 505 | ||||
-rw-r--r-- | spec/all.xml | 3 | ||||
-rw-r--r-- | spec/errors.xml | 10 | ||||
-rw-r--r-- | spec/generic-types.xml | 8 |
4 files changed, 525 insertions, 1 deletions
diff --git a/spec/Channel_Interface_Captcha_Authentication.xml b/spec/Channel_Interface_Captcha_Authentication.xml new file mode 100644 index 00000000..22f3440f --- /dev/null +++ b/spec/Channel_Interface_Captcha_Authentication.xml @@ -0,0 +1,505 @@ +<?xml version="1.0" ?> +<node name="/Channel_Interface_Captcha_Authentication" + xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <tp:copyright> Copyright © 2010-2012 Collabora Limited </tp:copyright> + <tp:license xmlns="http://www.w3.org/1999/xhtml"> + <p>This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version.</p> + +<p>This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details.</p> + +<p>You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> + </tp:license> + <interface name="org.freedesktop.Telepathy.Channel.Interface.CaptchaAuthentication1"> + <tp:added version="0.UNRELEASED">(version 1)</tp:added> + <tp:requires interface="org.freedesktop.Telepathy.Channel"/> + <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" + value="true"/> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>A channel interface for captcha authentication. + When this interface appears on a <tp:dbus-ref + namespace="ofdT.Channel.Type">ServerAuthentication</tp:dbus-ref> + channel, it represents authentication with the server. In future, + it could also be used to authenticate with secondary services, + or even to authenticate end-to-end connections with contacts. As a result, + this interface does not REQUIRE <tp:dbus-ref namespace="ofdT.Channel.Type" + >ServerAuthentication</tp:dbus-ref> to allow for a potential future + Channel.Type.PeerAuthentication interface.</p> + + <p>In any protocol that requires a captcha, the connection manager can + use this channel to let a user interface carry out a simple captcha + handshake with it, as a way to test the user is human + interactively.</p> + + <p>For channels managed by a + <tp:dbus-ref namespace="ofdT">ChannelDispatcher</tp:dbus-ref>, + only the channel's <tp:dbus-ref + namespace="ofdT.Client">Handler</tp:dbus-ref> may call the + methods on this interface. Other clients MAY observe the + authentication process by watching its signals and properties.</p> + + <p>The most commonly used form of captcha challenge is OCR (recognition + of distorted letters or words in an image), but for accessibility + reasons, this interface also allows various other types of challenge, + such as plain-text questions or recognition of words in audio. Its + structure is modelled on XMPP's + <a href="http://xmpp.org/extensions/xep-0158.html">XEP-0158</a>, + but can be used with other protocols by mapping their semantics + into those used in XMPP.</p> + + <tp:rationale> + <p>It is important to support multiple types of captcha + challenge to avoid discriminating against certain users; for + instance, blind or partially-sighted users cannot be expected + to answer an OCR challenge.</p> + + <p>XEP-0158 supports a superset of all other known protocols' captcha + interfaces, and is sufficiently elaborate that we expect it will + continue to do so.</p> + + <p>There can only be one Handler, which is a good fit for the + question/answer model implied by captchas.</p> + </tp:rationale> + </tp:docstring> + + <tp:struct name="Captcha_Info" array-name="Captcha_Info_List"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>A struct containing information regarding a single captcha + mechanism.</p> + </tp:docstring> + <tp:member type="u" name="ID"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The ID with which to reference this captcha method + when retrieving its data and answering it. + They are unique within this channel instance only.</p> + </tp:docstring> + </tp:member> + <tp:member type="s" name="Type"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The type of challenge + <a href="http://xmpp.org/extensions/xep-0158.html#challenge"> + as defined by XEP-0158</a>. For instance, the commonly-used + "type the letters/words you see in this image" challenge is + represented by <code>ocr</code></p> + </tp:docstring> + </tp:member> + <tp:member type="s" name="Label"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>A human-readable label for the challenge, as defined in + XEP-0158.</p> + + <p>If the server does not supply a label for a challenge of type + other than <code>qa</code>, connection managers SHOULD set Label + to an empty string instead of generating their own text. + If the Label is an empty string, the Handler SHOULD replace + it with a generic label in the user's locale, such as + the strings suggested in XEP-0158 (for instance, + <code>Enter the text you see</code> for <code>ocr</code> + challenges). The Handler MAY use those generic labels + in any case, as per + <a href="http://xmpp.org/extensions/xep-0158.html#i18n">the + Internationalization Considerations section of XEP-0158</a>.</p> + + <tp:rationale> + <p>Connection managers are not usually localized, so text + generated by the connection manager would be in English, + regardless of the user's locale. The Handler is better-placed + to generate a generic Label in the user's locale.</p> + </tp:rationale> + + <p>For challenges of type <code>qa</code>, the Label is a plain-text + question for the user to answer. The connection manager + SHOULD NOT provide an empty Label; if it does, the Handler + SHOULD treat that challenge as impossible, and SHOULD NOT + attempt to display it.</p> + </tp:docstring> + </tp:member> + <tp:member type="u" name="Flags" tp:type="Captcha_Flags"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>One flag defined: Required. Most captchas will have no flags.</p> + </tp:docstring> + </tp:member> + <tp:member type="as" name="Available_MIME_Types"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>A list of MIME types the server is offering to provide + for this captcha method.</p> + </tp:docstring> + </tp:member> + </tp:struct> + + <tp:mapping name="Captcha_Answers"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + A mapping of captcha IDs to answer strings. + </tp:docstring> + <tp:member type="u" name="ID"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + The ID of the captcha to which the associated + answer string is answering. + </tp:docstring> + </tp:member> + <tp:member type="s" name="Answer"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + The answer string to answer the captcha referenced + by the associated ID. + </tp:docstring> + </tp:member> + </tp:mapping> + + <property name="CanRetryCaptcha" + tp:name-for-bindings="Can_Retry_Captcha" + type="b" access="read" tp:immutable="yes"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>If true, <tp:member-ref>GetCaptchas</tp:member-ref> + can be expected to return new captcha information when + in the Local_Pending state. If false, + <tp:member-ref>GetCaptchas</tp:member-ref> will return + NotAvailable on subsequent calls.</p> + + <tp:rationale> + <p>Refreshing the captcha isn't required to work, although + some protocols and implementations allow it. This is usually + done in case a given captcha is unintelligible.</p> + </tp:rationale> + </tp:docstring> + </property> + + <property type="u" tp:type="Captcha_Status" access="read" + name="CaptchaStatus" tp:name-for-bindings="Captcha_Status"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The current status of this channel.</p> + + <p>Because only the Handler should call methods on this interface, + the Handler MAY reduce round-trips by not fetching the initial + value of this property, and instead assume that is initially + Local_Pending.</p> + + <tp:rationale> + <p>This assumption normally avoids the need to call GetAll(), + since the values of <tp:member-ref>CaptchaError</tp:member-ref> + and <tp:member-ref>CaptchaErrorDetails</tp:member-ref> + are also implied by this assumption, and the only other + property is <tp:member-ref>CanRetryCaptcha</tp:member-ref>, + which is immutable.</p> + </tp:rationale> + </tp:docstring> + </property> + + <property type="s" tp:type="DBus_Error_Name" access="read" + name="CaptchaError" tp:name-for-bindings="Captcha_Error"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>The reason for the <tp:member-ref>CaptchaStatus</tp:member-ref>, or + an empty string if the state is neither Try_Again nor Failed.</p> + + <p>Typical values: "", Cancelled, AuthenticationFailed, + CaptchaNotSupported</p> + + <p>In particular, an ordinary authentication failure (as would + be produced for an incorrect answer) SHOULD be represented by + <tp:error-ref>AuthenticationFailed</tp:error-ref>, + cancellation by the user's request SHOULD be represented + by <tp:error-ref>Cancelled</tp:error-ref>, cancellation due + to the inability to display the captcha to the user or otherwise + answer it SHOULD be represented by + <tp:error-ref>CaptchaNotSupported</tp:error-ref>, and + cancellation by a local process due to inconsistent or invalid + challenges from the server SHOULD be represented by + <tp:error-ref>ServiceConfused</tp:error-ref>.</p> + + <p>If this interface appears on a <tp:dbus-ref + namespace="ofdT.Channel.Type">ServerAuthentication</tp:dbus-ref> + channel, and connection to the server fails with an authentication + failure, this error code SHOULD be copied into the + <tp:dbus-ref + namespace="ofdT">Connection.ConnectionError</tp:dbus-ref> + signal.</p> + </tp:docstring> + </property> + + <property name="CaptchaErrorDetails" + tp:name-for-bindings="Captcha_Error_Details" + access="read" type="a{sv}" tp:type="String_Variant_Map"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>If <tp:member-ref>CaptchaError</tp:member-ref> is non-empty, + any additional information about the last + disconnection; otherwise, the empty map. The keys and values are + the same as for the second argument of + <tp:dbus-ref + namespace="ofdT">Connection.ConnectionError</tp:dbus-ref>.</p> + + <p>If this interface appears on a <tp:dbus-ref + namespace="ofdT.Channel.Type">ServerAuthentication</tp:dbus-ref> + channel, and connection to the server fails with an authentication + failure, these details SHOULD be copied into the + <tp:dbus-ref + namespace="ofdT">Connection.ConnectionError</tp:dbus-ref> + signal.</p> + </tp:docstring> + </property> + + <method name="GetCaptchas" tp:name-for-bindings="Get_Captchas"> + <arg direction="out" name="Captcha_Info" + type="a(ussuas)" tp:type="Captcha_Info[]"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + Information about each of the available captcha methods. + </tp:docstring> + </arg> + <arg direction="out" name="Number_Required" type="u"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + The number of captcha methods required to be answered + in order to successfully complete this captcha challenge + (most frequently 1, but XMPP allows servers to demand that + more than one captcha is answered). + </tp:docstring> + </arg> + <arg direction="out" name="Language" type="s" tp:type="Language_Tag"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + The language of each Label in Captcha_Info if available, + for instance en_US, or "" if unknown. + </tp:docstring> + </arg> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Gets information regarding each of the captcha methods + available and which and how many need to be successfully answered</p> + + <p>To call this method successfully, the state must be Local_Pending + or Try_Again. If it is Local_Pending, it remains Local_Pending. If + called more than once while in Local_Pending state, or if the state + is Try_Again, this method fetches a new set of captcha challenges, + if possible, and the state returns to Local_Pending.</p> + + <tp:rationale> + <p>For instance, you could call GetCaptchas again from Local_Pending + state if the user indicates that they can't understand the + initially-offered captcha.</p> + + <p>This is a method, not a property, so that it can be used to + fetch more than one set of captcha challenges, and so that + change notification is not required. Only the Handler should + call this method and calling GetAll would not reduce round-trips, + so the usual reasons to prefer a property do not apply here.</p> + </tp:rationale> + </tp:docstring> + + <tp:possible-errors> + <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable"> + <tp:docstring> + Either the state is not Local_Pending or Try_Again, or it has + already been called and + <tp:member-ref>CanRetryCaptcha</tp:member-ref> is False. + </tp:docstring> + </tp:error> + <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/> + </tp:possible-errors> + </method> + + <method name="GetCaptchaData" tp:name-for-bindings="Get_Captcha_Data"> + <arg direction="in" name="ID" type="u"> + <tp:docstring> + The ID of the captcha of which to retrieve data. + </tp:docstring> + </arg> + <arg direction="in" name="Mime_Type" type="s"> + <tp:docstring> + MIME type picked by the Handler, chosen from the list of MIME + types received in <tp:member-ref>GetCaptchas</tp:member-ref>. + <tp:rationale> + XEP-0158 allows the same captcha to be made available in + multiple formats, for instance the same spoken question as + audio/x-wav, application/ogg and audio/speex. + </tp:rationale> + </tp:docstring> + </arg> + <arg direction="out" name="Captcha_Data" type="ay"> + <tp:docstring> + Captcha data as requested. + </tp:docstring> + </arg> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Fetch and return the captcha data. In protocols + where captchas are downloaded out-of-band (for instance via HTTP), + the connection manager is expected to do so.</p> + <p>Returns an empty array if the type was "qa"</p> + <tp:rationale> + <p>If audio-based and image-based captchas are both available, + we don't want to waste time downloading the audio until/unless + the user asks to hear it. The extra D-Bus round-trips are not + a problem, since they are expected to be quick compared with + the time taken for the user to solve the captcha.</p> + </tp:rationale> + </tp:docstring> + <tp:possible-errors> + <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable"> + <tp:docstring> + The state is not in Local_Pending or + <tp:member-ref>GetCaptchas</tp:member-ref> had never been called. + </tp:docstring> + </tp:error> + <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/> + </tp:possible-errors> + </method> + + <method name="AnswerCaptchas" tp:name-for-bindings="Answer_Captchas"> + <arg direction="in" name="Answers" + type="a{us}" tp:type="Captcha_Answers"> + <tp:docstring> + The mapping of captcha IDs to answer strings. + </tp:docstring> + </arg> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Answer as many captchas as desired and/or required.</p> + <p>Callable in state Local_Pending only. State changes to + Remote_Pending.</p> + </tp:docstring> + + <tp:possible-errors> + <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable"> + <tp:docstring> + The state is not in Local_Pending. + </tp:docstring> + </tp:error> + <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/> + </tp:possible-errors> + </method> + + <method name="CancelCaptcha" tp:name-for-bindings="Cancel_Captcha"> + <arg direction="in" name="Reason" + type="u" tp:type="Captcha_Cancel_Reason"> + <tp:docstring> + Reason for cancelling. This MAY be used to choose an error + response to the remote server, and SHOULD also be reflected + in the <tp:member-ref>CaptchaError</tp:member-ref>. + </tp:docstring> + </arg> + <arg direction="in" name="Debug_Message" type="s"> + <tp:docstring> + A textual description of the reason for cancelling, supplied + by the Handler. This message SHOULD NOT be sent to the remote + server, but SHOULD be copied into the 'debug-message' field + of the <tp:member-ref>CaptchaErrorDetails</tp:member-ref> and + <tp:dbus-ref namespace="ofdT.Connection">ConnectionError</tp:dbus-ref>. + </tp:docstring> + </arg> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Cancel. State changes to Failed with error NotAvailable or + Cancelled if it isn't already Failed. All you can do now is + to close the channel.</p> + </tp:docstring> + <tp:possible-errors> + <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable"> + <tp:docstring> + The current state is Failed. + </tp:docstring> + </tp:error> + </tp:possible-errors> + </method> + + <tp:flags name="Captcha_Flags" type="u"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Extra flags to include with Captcha information</p> + </tp:docstring> + + <tp:flag suffix="Required" value="1"> + <tp:docstring> + This captcha mechanism is required to be successfully + answered in order to pass this captcha challenge. + </tp:docstring> + </tp:flag> + </tp:flags> + + <tp:enum name="Captcha_Cancel_Reason" type="u"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>A reason why captcha authentication was aborted by the client.</p> + </tp:docstring> + + <tp:enumvalue suffix="User_Cancelled" value="0"> + <tp:docstring> + The user aborted the authentication. If this is used, the + <tp:member-ref>CaptchaError</tp:member-ref> SHOULD be set to + <tp:error-ref>Cancelled</tp:error-ref> + </tp:docstring> + </tp:enumvalue> + <tp:enumvalue suffix="Not_Supported" value="1"> + <tp:docstring> + The Handler doesn't support the given/required captcha types. + If this is used, the <tp:member-ref>CaptchaError</tp:member-ref> + SHOULD be set to <tp:error-ref>CaptchaNotSupported</tp:error-ref>. + This SHOULD also be used if + <tp:dbus-ref namespace="ofdT.Channel">Close</tp:dbus-ref> is called + before <tp:member-ref>CancelCaptcha</tp:member-ref>. + <tp:rationale> + If no Handler supports captcha channels, + the ChannelDispatcher will just call + <tp:dbus-ref namespace="ofdT.Channel">Close</tp:dbus-ref>, + because it has no knowledge of specific channel types. + </tp:rationale> + </tp:docstring> + </tp:enumvalue> + <tp:enumvalue suffix="Service_Confused" value="2"> + <tp:docstring> + The Handler doesn't understand the captcha data received. The + challenger may be sending gibberish. + If this is used, the <tp:member-ref>CaptchaError</tp:member-ref> + SHOULD be set to <tp:error-ref>ServiceConfused</tp:error-ref>. + </tp:docstring> + </tp:enumvalue> + </tp:enum> + + <tp:enum name="Captcha_Status" type="u" plural="Captcha_Statuses"> + <tp:enumvalue suffix="Local_Pending" value="0"> + <tp:docstring> + The challenge/response exchange is in progress and waiting for + a local action. Call <tp:member-ref>AnswerCaptchas</tp:member-ref> + to go to the Remote_Pending state, or call + <tp:member-ref>CancelCaptcha</tp:member-ref> followed by + <tp:dbus-ref namespace="ofdT.Channel">Close</tp:dbus-ref> + to give up. + </tp:docstring> + </tp:enumvalue> + <tp:enumvalue suffix="Remote_Pending" value="1"> + <tp:docstring> + The challenge/response exchange is in progress and waiting for + a response from the server. Wait for a reply from the server, + which will result in the Succeeded, Try_Again, or Failed state, + or call <tp:member-ref>CancelCaptcha</tp:member-ref> followed by + <tp:dbus-ref namespace="ofdT.Channel">Close</tp:dbus-ref> + to give up. + </tp:docstring> + </tp:enumvalue> + <tp:enumvalue suffix="Succeeded" value="2"> + <tp:docstring> + Everyone is happy. Connection to the server will proceed as soon as + this state is reached. There is nothing useful to do in this state + except to call <tp:dbus-ref + namespace="ofdT.Channel">Close</tp:dbus-ref> + to close the channel. + </tp:docstring> + </tp:enumvalue> + <tp:enumvalue suffix="Try_Again" value="3"> + <tp:docstring> + The server has indicated an authentication failure. + Call <tp:member-ref>GetCaptchas</tp:member-ref> again to get + a new captcha, or + <tp:member-ref>CancelCaptcha</tp:member-ref> followed by + <tp:dbus-ref namespace="ofdT.Channel">Close</tp:dbus-ref> + to give up. + </tp:docstring> + </tp:enumvalue> + <tp:enumvalue suffix="Failed" value="4"> + <tp:docstring> + Authentication has failed in some way. There is nothing + useful to do in this state except to close the channel with + <tp:dbus-ref namespace="ofdT.Channel">Close</tp:dbus-ref>. + </tp:docstring> + </tp:enumvalue> + </tp:enum> + + </interface> +</node> +<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/spec/all.xml b/spec/all.xml index 72e4c491..186fbfc1 100644 --- a/spec/all.xml +++ b/spec/all.xml @@ -5,7 +5,7 @@ <tp:title>Telepathy D-Bus Interface Specification</tp:title> <tp:version>0.25.1.1</tp:version> -<tp:copyright>Copyright © 2005-2011 Collabora Limited</tp:copyright> +<tp:copyright>Copyright © 2005-2012 Collabora Limited</tp:copyright> <tp:copyright>Copyright © 2005-2011 Nokia Corporation</tp:copyright> <tp:copyright>Copyright © 2006 INdT</tp:copyright> @@ -168,6 +168,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</ <xi:include href="Channel_Interface_Room.xml"/> <xi:include href="Channel_Interface_Room_Config.xml"/> <xi:include href="Channel_Interface_SASL_Authentication.xml"/> + <xi:include href="Channel_Interface_Captcha_Authentication.xml"/> <xi:include href="Channel_Interface_Credentials_Storage.xml"/> <xi:include href="Channel_Interface_Securable.xml"/> <xi:include href="Channel_Interface_Service_Point.xml"/> diff --git a/spec/errors.xml b/spec/errors.xml index 7726f3cf..c9e85dd3 100644 --- a/spec/errors.xml +++ b/spec/errors.xml @@ -637,6 +637,16 @@ </tp:docstring> </tp:error> + <tp:error name="Captcha Not Supported"> + <tp:added version="0.UNRELEASED"/> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Raised if the <tp:dbus-ref + namespace="ofdT.Channel.Interface">CaptchaAuthentication1</tp:dbus-ref> + Handler either has no UI to present captchas, or it does, but wasn't + able to answer any of the captchas given.</p> + </tp:docstring> + </tp:error> + <tp:copyright>Copyright © 2005-2010 Collabora Limited</tp:copyright> <tp:copyright>Copyright © 2005-2009 Nokia Corporation</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> diff --git a/spec/generic-types.xml b/spec/generic-types.xml index 014f8ada..2676e453 100644 --- a/spec/generic-types.xml +++ b/spec/generic-types.xml @@ -212,4 +212,12 @@ </tp:member> </tp:mapping> + <tp:simple-type name="Language_Tag" type="s"> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + A language tag as defined in + <a href="https://www.rfc-editor.org/rfc/bcp/bcp47.txt">IETF BCP 47</a>, + such as "en_US". + </tp:docstring> + </tp:simple-type> + </tp:generic-types> |