Commit 741ccd50 authored by Peter Eisentraut's avatar Peter Eisentraut

Use gender-neutral language in documentation

Based on patch by Thomas Munro <thomas.munro@enterprisedb.com>, although
I rephrased most of the initial work.
parent 13200777
...@@ -9274,7 +9274,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx ...@@ -9274,7 +9274,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
<filename>postgresql.conf</filename> without restarting the server. <filename>postgresql.conf</filename> without restarting the server.
They can also be set for a particular session in the connection request They can also be set for a particular session in the connection request
packet (for example, via <application>libpq</>'s <literal>PGOPTIONS</> packet (for example, via <application>libpq</>'s <literal>PGOPTIONS</>
environment variable); any user can make such a change for his session. environment variable); any user can make such a change for their session.
However, these settings never change in a session after it is started. However, these settings never change in a session after it is started.
If you change them in <filename>postgresql.conf</filename>, send a If you change them in <filename>postgresql.conf</filename>, send a
<systemitem>SIGHUP</systemitem> signal to the postmaster to cause it to <systemitem>SIGHUP</systemitem> signal to the postmaster to cause it to
...@@ -9303,7 +9303,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx ...@@ -9303,7 +9303,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
<para> <para>
These settings can be set from <filename>postgresql.conf</filename>, These settings can be set from <filename>postgresql.conf</filename>,
or within a session via the <command>SET</> command. Any user is or within a session via the <command>SET</> command. Any user is
allowed to change his session-local value. Changes in allowed to change their session-local value. Changes in
<filename>postgresql.conf</filename> will affect existing sessions <filename>postgresql.conf</filename> will affect existing sessions
only if no session-local value has been established with <command>SET</>. only if no session-local value has been established with <command>SET</>.
</para> </para>
......
...@@ -690,9 +690,9 @@ local db1,db2,@demodbs all md5 ...@@ -690,9 +690,9 @@ local db1,db2,@demodbs all md5
</indexterm> </indexterm>
<para> <para>
When using an external authentication system like Ident or GSSAPI, When using an external authentication system such as Ident or GSSAPI,
the name of the operating system user that initiated the connection the name of the operating system user that initiated the connection
might not be the same as the database user he needs to connect as. might not be the same as the database user that is to be connect as.
In this case, a user name map can be applied to map the operating system In this case, a user name map can be applied to map the operating system
user name to a database user. To use user name mapping, specify user name to a database user. To use user name mapping, specify
<literal>map</literal>=<replaceable>map-name</replaceable> <literal>map</literal>=<replaceable>map-name</replaceable>
...@@ -1185,7 +1185,7 @@ omicron bryanh guest1 ...@@ -1185,7 +1185,7 @@ omicron bryanh guest1
The drawback of this procedure is that it depends on the integrity The drawback of this procedure is that it depends on the integrity
of the client: if the client machine is untrusted or compromised, of the client: if the client machine is untrusted or compromised,
an attacker could run just about any program on port 113 and an attacker could run just about any program on port 113 and
return any user name he chooses. This authentication method is return any user name they choose. This authentication method is
therefore only appropriate for closed networks where each client therefore only appropriate for closed networks where each client
machine is under tight control and where the database and system machine is under tight control and where the database and system
administrators operate in close contact. In other words, you must administrators operate in close contact. In other words, you must
......
...@@ -1492,8 +1492,8 @@ REVOKE ALL ON accounts FROM PUBLIC; ...@@ -1492,8 +1492,8 @@ REVOKE ALL ON accounts FROM PUBLIC;
<command>DROP</>, <command>GRANT</>, <command>REVOKE</>, etc.) <command>DROP</>, <command>GRANT</>, <command>REVOKE</>, etc.)
are always implicit in being the owner, are always implicit in being the owner,
and cannot be granted or revoked. But the object owner can choose and cannot be granted or revoked. But the object owner can choose
to revoke his own ordinary privileges, for example to make a to revoke their own ordinary privileges, for example to make a
table read-only for himself as well as others. table read-only for themselves as well as others.
</para> </para>
<para> <para>
...@@ -1816,7 +1816,7 @@ UPDATE 1 ...@@ -1816,7 +1816,7 @@ UPDATE 1
example, both <literal>schema1</> and <literal>myschema</> can example, both <literal>schema1</> and <literal>myschema</> can
contain tables named <literal>mytable</>. Unlike databases, contain tables named <literal>mytable</>. Unlike databases,
schemas are not rigidly separated: a user can access objects in any schemas are not rigidly separated: a user can access objects in any
of the schemas in the database he is connected to, if he has of the schemas in the database they are connected to, if they have
privileges to do so. privileges to do so.
</para> </para>
......
...@@ -155,9 +155,9 @@ createdb <replaceable class="parameter">dbname</replaceable> ...@@ -155,9 +155,9 @@ createdb <replaceable class="parameter">dbname</replaceable>
</note> </note>
<para> <para>
Sometimes you want to create a database for someone else, and have him Sometimes you want to create a database for someone else, and have them
become the owner of the new database, so he can become the owner of the new database, so they can
configure and manage it himself. To achieve that, use one of the configure and manage it themselves. To achieve that, use one of the
following commands: following commands:
<programlisting> <programlisting>
CREATE DATABASE <replaceable>dbname</> OWNER <replaceable>rolename</>; CREATE DATABASE <replaceable>dbname</> OWNER <replaceable>rolename</>;
......
...@@ -115,7 +115,7 @@ msgstr "another translated" ...@@ -115,7 +115,7 @@ msgstr "another translated"
for the translator, such as about expected alignment. The #: for the translator, such as about expected alignment. The #:
comment indicates the exact location(s) where the message is used comment indicates the exact location(s) where the message is used
in the source. The translator need not look at the program in the source. The translator need not look at the program
source, but he can if there is doubt about the correct source, but can if there is doubt about the correct
translation. The #, comments contain flags that describe the translation. The #, comments contain flags that describe the
message in some way. There are currently two flags: message in some way. There are currently two flags:
<literal>fuzzy</literal> is set if the message has possibly been <literal>fuzzy</literal> is set if the message has possibly been
......
...@@ -3904,7 +3904,7 @@ CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$ ...@@ -3904,7 +3904,7 @@ CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
RAISE EXCEPTION '% cannot have null salary', NEW.empname; RAISE EXCEPTION '% cannot have null salary', NEW.empname;
END IF; END IF;
-- Who works for us when she must pay for it? -- Who works for us when they must pay for it?
IF NEW.salary &lt; 0 THEN IF NEW.salary &lt; 0 THEN
RAISE EXCEPTION '% cannot have a negative salary', NEW.empname; RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
END IF; END IF;
......
...@@ -38,7 +38,7 @@ ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> ...@@ -38,7 +38,7 @@ ALTER USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable>
<para> <para>
The owner of a foreign server can alter user mappings for that The owner of a foreign server can alter user mappings for that
server for any user. Also, a user can alter a user mapping for server for any user. Also, a user can alter a user mapping for
his own user name if <literal>USAGE</> privilege on the server has their own user name if <literal>USAGE</> privilege on the server has
been granted to the user. been granted to the user.
</para> </para>
</refsect1> </refsect1>
......
...@@ -205,7 +205,7 @@ CREATE VIEW hollywood.winners AS ...@@ -205,7 +205,7 @@ CREATE VIEW hollywood.winners AS
all objects within it. <productname>PostgreSQL</productname> all objects within it. <productname>PostgreSQL</productname>
allows schemas to contain objects owned by users other than the allows schemas to contain objects owned by users other than the
schema owner. This can happen only if the schema owner grants the schema owner. This can happen only if the schema owner grants the
<literal>CREATE</> privilege on his schema to someone else, or a <literal>CREATE</> privilege on their schema to someone else, or a
superuser chooses to create objects in it. superuser chooses to create objects in it.
</para> </para>
......
...@@ -41,7 +41,7 @@ CREATE USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable> ...@@ -41,7 +41,7 @@ CREATE USER MAPPING FOR { <replaceable class="parameter">user_name</replaceable>
<para> <para>
The owner of a foreign server can create user mappings for that The owner of a foreign server can create user mappings for that
server for any user. Also, a user can create a user mapping for server for any user. Also, a user can create a user mapping for
his own user name if <literal>USAGE</> privilege on the server has their own user name if <literal>USAGE</> privilege on the server has
been granted to the user. been granted to the user.
</para> </para>
</refsect1> </refsect1>
......
...@@ -35,7 +35,7 @@ DROP SCHEMA [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, . ...@@ -35,7 +35,7 @@ DROP SCHEMA [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable> [, .
<para> <para>
A schema can only be dropped by its owner or a superuser. Note that A schema can only be dropped by its owner or a superuser. Note that
the owner can drop the schema (and thereby all contained objects) the owner can drop the schema (and thereby all contained objects)
even if he does not own some of the objects within the schema. even if they do not own some of the objects within the schema.
</para> </para>
</refsect1> </refsect1>
......
...@@ -35,7 +35,7 @@ DROP USER MAPPING [ IF EXISTS ] FOR { <replaceable class="parameter">user_name</ ...@@ -35,7 +35,7 @@ DROP USER MAPPING [ IF EXISTS ] FOR { <replaceable class="parameter">user_name</
<para> <para>
The owner of a foreign server can drop user mappings for that server The owner of a foreign server can drop user mappings for that server
for any user. Also, a user can drop a user mapping for his own for any user. Also, a user can drop a user mapping for their own
user name if <literal>USAGE</> privilege on the server has been user name if <literal>USAGE</> privilege on the server has been
granted to the user. granted to the user.
</para> </para>
......
...@@ -141,7 +141,7 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace ...@@ -141,7 +141,7 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace
There is no need to grant privileges to the owner of an object There is no need to grant privileges to the owner of an object
(usually the user that created it), (usually the user that created it),
as the owner has all privileges by default. (The owner could, as the owner has all privileges by default. (The owner could,
however, choose to revoke some of his own privileges for safety.) however, choose to revoke some of their own privileges for safety.)
</para> </para>
<para> <para>
...@@ -365,7 +365,7 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace ...@@ -365,7 +365,7 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace
</para> </para>
<para> <para>
For servers, this privilege enables the grantee to create foreign For servers, this privilege enables the grantee to create foreign
tables using the server, and also to create, alter, or drop his own tables using the server, and also to create, alter, or drop their own
user's user mappings associated with that server. user's user mappings associated with that server.
</para> </para>
</listitem> </listitem>
...@@ -438,9 +438,9 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace ...@@ -438,9 +438,9 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace
<para> <para>
A user may perform <command>SELECT</>, <command>INSERT</>, etc. on a A user may perform <command>SELECT</>, <command>INSERT</>, etc. on a
column if he holds that privilege for either the specific column or column if they hold that privilege for either the specific column or
its whole table. Granting the privilege at the table level and then its whole table. Granting the privilege at the table level and then
revoking it for one column will not do what you might wish: the revoking it for one column will not do what one might wish: the
table-level grant is unaffected by a column-level operation. table-level grant is unaffected by a column-level operation.
</para> </para>
...@@ -626,13 +626,13 @@ GRANT admins TO joe; ...@@ -626,13 +626,13 @@ GRANT admins TO joe;
</para> </para>
<para> <para>
<productname>PostgreSQL</productname> allows an object owner to revoke his <productname>PostgreSQL</productname> allows an object owner to revoke their
own ordinary privileges: for example, a table owner can make the table own ordinary privileges: for example, a table owner can make the table
read-only to himself by revoking his own <literal>INSERT</>, read-only to themselves by revoking their own <literal>INSERT</>,
<literal>UPDATE</>, <literal>DELETE</>, and <literal>TRUNCATE</> <literal>UPDATE</>, <literal>DELETE</>, and <literal>TRUNCATE</>
privileges. This is not possible according to the SQL standard. The privileges. This is not possible according to the SQL standard. The
reason is that <productname>PostgreSQL</productname> treats the owner's reason is that <productname>PostgreSQL</productname> treats the owner's
privileges as having been granted by the owner to himself; therefore he privileges as having been granted by the owner to themselves; therefore they
can revoke them too. In the SQL standard, the owner's privileges are can revoke them too. In the SQL standard, the owner's privileges are
granted by an assumed entity <quote>_SYSTEM</>. Not being granted by an assumed entity <quote>_SYSTEM</>. Not being
<quote>_SYSTEM</>, the owner cannot revoke these rights. <quote>_SYSTEM</>, the owner cannot revoke these rights.
......
...@@ -193,7 +193,7 @@ REVOKE [ ADMIN OPTION FOR ] ...@@ -193,7 +193,7 @@ REVOKE [ ADMIN OPTION FOR ]
Instead, user A could revoke the grant option from user B and use Instead, user A could revoke the grant option from user B and use
the <literal>CASCADE</literal> option so that the privilege is the <literal>CASCADE</literal> option so that the privilege is
in turn revoked from user C. For another example, if both A and B in turn revoked from user C. For another example, if both A and B
have granted the same privilege to C, A can revoke his own grant have granted the same privilege to C, A can revoke their own grant
but not B's grant, so C will still effectively have the privilege. but not B's grant, so C will still effectively have the privilege.
</para> </para>
......
...@@ -77,7 +77,7 @@ RESET ROLE ...@@ -77,7 +77,7 @@ RESET ROLE
<para> <para>
In particular, when a superuser chooses to <command>SET ROLE</> to a In particular, when a superuser chooses to <command>SET ROLE</> to a
non-superuser role, she loses her superuser privileges. non-superuser role, they lose their superuser privileges.
</para> </para>
<para> <para>
......
...@@ -1652,7 +1652,7 @@ CREATE RULE shoelace_ins AS ON INSERT TO shoelace ...@@ -1652,7 +1652,7 @@ CREATE RULE shoelace_ins AS ON INSERT TO shoelace
Now assume that once in a while, a pack of shoelaces arrives at Now assume that once in a while, a pack of shoelaces arrives at
the shop and a big parts list along with it. But you don't want the shop and a big parts list along with it. But you don't want
to manually update the <literal>shoelace</literal> view every to manually update the <literal>shoelace</literal> view every
time. Instead we setup two little tables: one where you can time. Instead we set up two little tables: one where you can
insert the items from the part list, and one with a special insert the items from the part list, and one with a special
trick. The creation commands for these are: trick. The creation commands for these are:
...@@ -2023,57 +2023,57 @@ SELECT * FROM shoelace; ...@@ -2023,57 +2023,57 @@ SELECT * FROM shoelace;
behavior of the default access control system. Relations that behavior of the default access control system. Relations that
are used due to rules get checked against the are used due to rules get checked against the
privileges of the rule owner, not the user invoking the rule. privileges of the rule owner, not the user invoking the rule.
This means that a user only needs the required privileges This means that users only need the required privileges
for the tables/views that he names explicitly in his queries. for the tables/views that are explicitly named in their queries.
</para> </para>
<para> <para>
For example: A user has a list of phone numbers where some of For example: A user has a list of phone numbers where some of
them are private, the others are of interest for the secretary of the office. them are private, the others are of interest for the assistant of the office.
He can construct the following: The user can construct the following:
<programlisting> <programlisting>
CREATE TABLE phone_data (person text, phone text, private boolean); CREATE TABLE phone_data (person text, phone text, private boolean);
CREATE VIEW phone_number AS CREATE VIEW phone_number AS
SELECT person, CASE WHEN NOT private THEN phone END AS phone SELECT person, CASE WHEN NOT private THEN phone END AS phone
FROM phone_data; FROM phone_data;
GRANT SELECT ON phone_number TO secretary; GRANT SELECT ON phone_number TO assistant;
</programlisting> </programlisting>
Nobody except him (and the database superusers) can access the Nobody except that user (and the database superusers) can access the
<literal>phone_data</> table. But because of the <command>GRANT</>, <literal>phone_data</> table. But because of the <command>GRANT</>,
the secretary can run a <command>SELECT</command> on the the assistant can run a <command>SELECT</command> on the
<literal>phone_number</> view. The rule system will rewrite the <literal>phone_number</> view. The rule system will rewrite the
<command>SELECT</command> from <literal>phone_number</> into a <command>SELECT</command> from <literal>phone_number</> into a
<command>SELECT</command> from <literal>phone_data</>. <command>SELECT</command> from <literal>phone_data</>.
Since the user is the owner of Since the user is the owner of
<literal>phone_number</> and therefore the owner of the rule, the <literal>phone_number</> and therefore the owner of the rule, the
read access to <literal>phone_data</> is now checked against his read access to <literal>phone_data</> is now checked against the user's
privileges and the query is permitted. The check for accessing privileges and the query is permitted. The check for accessing
<literal>phone_number</> is also performed, but this is done <literal>phone_number</> is also performed, but this is done
against the invoking user, so nobody but the user and the against the invoking user, so nobody but the user and the
secretary can use it. assistant can use it.
</para> </para>
<para> <para>
The privileges are checked rule by rule. So the secretary is for now the The privileges are checked rule by rule. So the assistant is for now the
only one who can see the public phone numbers. But the secretary can setup only one who can see the public phone numbers. But the assistant can set up
another view and grant access to that to the public. Then, anyone another view and grant access to that to the public. Then, anyone
can see the <literal>phone_number</> data through the secretary's view. can see the <literal>phone_number</> data through the assistant's view.
What the secretary cannot do is to create a view that directly What the assistant cannot do is to create a view that directly
accesses <literal>phone_data</>. (Actually he can, but it will not work since accesses <literal>phone_data</>. (Actually the assistant can, but it will not work since
every access will be denied during the permission checks.) every access will be denied during the permission checks.)
And as soon as the user will notice, that the secretary opened And as soon as the user notices that the assistant opened
his <literal>phone_number</> view, he can revoke his access. Immediately, any their <literal>phone_number</> view, the user can revoke the assistant's access. Immediately, any
access to the secretary's view would fail. access to the assistant's view would fail.
</para> </para>
<para> <para>
One might think that this rule-by-rule checking is a security One might think that this rule-by-rule checking is a security
hole, but in fact it isn't. But if it did not work this way, the secretary hole, but in fact it isn't. But if it did not work this way, the assistant
could set up a table with the same columns as <literal>phone_number</> and could set up a table with the same columns as <literal>phone_number</> and
copy the data to there once per day. Then it's his own data and copy the data to there once per day. Then it's the assistant's own data and
he can grant access to everyone he wants. A the assistant can grant access to everyone they want. A
<command>GRANT</command> command means, <quote>I trust you</quote>. <command>GRANT</command> command means, <quote>I trust you</quote>.
If someone you trust does the thing above, it's time to If someone you trust does the thing above, it's time to
think it over and then use <command>REVOKE</command>. think it over and then use <command>REVOKE</command>.
...@@ -2093,7 +2093,7 @@ CREATE VIEW phone_number AS ...@@ -2093,7 +2093,7 @@ CREATE VIEW phone_number AS
<command>SELECT</command> from <literal>phone_number</> into a <command>SELECT</command> from <literal>phone_number</> into a
<command>SELECT</command> from <literal>phone_data</> and add the <command>SELECT</command> from <literal>phone_data</> and add the
qualification that only entries where <literal>phone</> does not begin qualification that only entries where <literal>phone</> does not begin
with 412 are wanted. But if the user can create his or her own functions, with 412 are wanted. But if the user can create their own functions,
it is not difficult to convince the planner to execute the user-defined it is not difficult to convince the planner to execute the user-defined
function prior to the <function>NOT LIKE</function> expression. function prior to the <function>NOT LIKE</function> expression.
For example: For example:
...@@ -2124,8 +2124,8 @@ SELECT * FROM phone_number WHERE tricky(person, phone); ...@@ -2124,8 +2124,8 @@ SELECT * FROM phone_number WHERE tricky(person, phone);
the <literal>shoelace</> view to someone else, but only the <literal>shoelace</> view to someone else, but only
<literal>SELECT</> on <literal>shoelace_log</>. The rule action to <literal>SELECT</> on <literal>shoelace_log</>. The rule action to
write log entries will still be executed successfully, and that write log entries will still be executed successfully, and that
other user could see the log entries. But he cannot create fake other user could see the log entries. But they could not create fake
entries, nor could he manipulate or remove existing ones. In this entries, nor could they manipulate or remove existing ones. In this
case, there is no possibility of subverting the rules by convincing case, there is no possibility of subverting the rules by convincing
the planner to alter the order of operations, because the only rule the planner to alter the order of operations, because the only rule
which references <literal>shoelace_log</> is an unqualified which references <literal>shoelace_log</> is an unqualified
...@@ -2333,7 +2333,7 @@ DELETE FROM software WHERE computer.hostname = 'mypc.local.net' ...@@ -2333,7 +2333,7 @@ DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
AND software.hostname = computer.hostname; AND software.hostname = computer.hostname;
</programlisting> </programlisting>
Since there are appropriate indexes setup, the planner Since there are appropriate indexes set up, the planner
will create a plan of will create a plan of
<literallayout class="monospaced"> <literallayout class="monospaced">
......
...@@ -570,7 +570,7 @@ postgres=# SELECT cid, cname, show_credit(cid) FROM customer; ...@@ -570,7 +570,7 @@ postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
<para> <para>
In this case, a regular user cannot reference <literal>customer.credit</> In this case, a regular user cannot reference <literal>customer.credit</>
directly, but a trusted procedure <literal>show_credit</> allows him directly, but a trusted procedure <literal>show_credit</> allows the user
to print the credit card numbers of customers with some of the digits to print the credit card numbers of customers with some of the digits
masked out. masked out.
</para> </para>
......
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
Returns serial number of current client certificate. The combination of Returns serial number of current client certificate. The combination of
certificate serial number and certificate issuer is guaranteed to certificate serial number and certificate issuer is guaranteed to
uniquely identify a certificate (but not its owner &mdash; the owner uniquely identify a certificate (but not its owner &mdash; the owner
ought to regularly change his keys, and get new certificates from the ought to regularly change their keys, and get new certificates from the
issuer). issuer).
</para> </para>
......
...@@ -143,8 +143,7 @@ ...@@ -143,8 +143,7 @@
<para> <para>
Possibly, your site administrator has already created a database Possibly, your site administrator has already created a database
for your use. He should have told you what the name of your for your use. In that case you can omit this step and skip ahead
database is. In that case you can omit this step and skip ahead
to the next section. to the next section.
</para> </para>
......
...@@ -129,7 +129,7 @@ SELECT rolname FROM pg_roles; ...@@ -129,7 +129,7 @@ SELECT rolname FROM pg_roles;
<xref linkend="client-authentication">. (Thus, a client is not <xref linkend="client-authentication">. (Thus, a client is not
limited to connect as the role matching limited to connect as the role matching
its operating system user, just as a person's login name its operating system user, just as a person's login name
need not match her real name.) Since the role need not match his or her real name.) Since the role
identity determines the set of privileges available to a connected identity determines the set of privileges available to a connected
client, it is important to carefully configure privileges when setting up client, it is important to carefully configure privileges when setting up
a multiuser environment. a multiuser environment.
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
<literal>template1</> will be copied by <command>CREATE DATABASE</>. <literal>template1</> will be copied by <command>CREATE DATABASE</>.
So the database administrator can So the database administrator can
decide which languages are available in which databases and can make decide which languages are available in which databases and can make
some languages available by default if he chooses. some languages available by default if desired.
</para> </para>
<para> <para>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment