diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py
new file mode 100644
index 0000000..03e135c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py
@@ -0,0 +1,511 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import json
+from flask import render_template, make_response, request, jsonify
+from flask.ext.babel import gettext
+from pgadmin.utils.ajax import make_json_response, \
+    make_response as ajax_response, internal_server_error
+from pgadmin.browser.utils import NodeView
+from pgadmin.browser.collection import CollectionNodeModule
+import pgadmin.browser.server_groups.servers.databases as databases
+from pgadmin.utils.ajax import precondition_required
+from pgadmin.utils.driver import get_driver
+from config import PG_DEFAULT_DRIVER
+from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
+    parse_priv_to_db
+from functools import wraps
+from pgadmin.browser.server_groups.servers.depends import get_dependencies, get_dependents
+
+
+class LanguageModule(CollectionNodeModule):
+    """
+    class LanguageModule(CollectionNodeModule)
+
+        A module class for Language node derived from CollectionNodeModule.
+
+    Methods:
+    -------
+    * __init__(*args, **kwargs)
+      - Method is used to initialize the LanguageModule and it's base module.
+
+    * get_nodes(gid, sid, did)
+      - Method is used to generate the browser collection node.
+
+    * node_inode()
+      - Method is overridden from its base class to make the node as leaf node.
+
+    * script_load()
+      - Load the module script for language, when any of the database node is
+        initialized.
+    """
+
+    NODE_TYPE = 'language'
+    COLLECTION_LABEL = gettext("Languages")
+
+    def __init__(self, *args, **kwargs):
+        """
+        Method is used to initialize the LanguageModule and it's base module.
+
+        Args:
+            *args:
+            **kwargs:
+        """
+        self.min_ver = None
+        self.max_ver = None
+
+        super(LanguageModule, self).__init__(*args, **kwargs)
+
+    def get_nodes(self, gid, sid, did):
+        """
+        Method is used to generate the browser collection node
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database Id
+        """
+        yield self.generate_browser_collection_node(did)
+
+    @property
+    def node_inode(self):
+        """
+        Override this property to make the node as leaf node.
+
+        Returns: False as this is the leaf node
+        """
+        return False
+
+    @property
+    def script_load(self):
+        """
+        Load the module script for language, when any of the database node is initialized.
+
+        Returns: node type of the server module.
+        """
+        return databases.DatabaseModule.NODE_TYPE
+
+blueprint = LanguageModule(__name__)
+
+
+class LanguageView(NodeView):
+    """
+    class LanguageView(NodeView)
+
+        A view class for Language node derived from NodeView. This class is
+        responsible for all the stuff related to view like updating language
+        node, showing properties, showing sql in sql pane.
+
+    Methods:
+    -------
+    * __init__(**kwargs)
+      - Method is used to initialize the LanguageView and it's base view.
+
+    * module_js()
+      - This property defines (if javascript) exists for this node.
+        Override this property for your own logic
+
+    * check_precondition()
+      - This function will behave as a decorator which will checks
+        database connection before running view, it will also attaches
+        manager,conn & template_path properties to self
+
+    * list()
+      - This function is used to list all the language nodes within that collection.
+
+    * nodes()
+      - This function will used to create all the child node within that collection.
+        Here it will create all the language node.
+
+    * properties(gid, sid, did, lid)
+      - This function will show the properties of the selected language node
+
+    * update(gid, sid, did, lid)
+      - This function will update the data for the selected language node
+
+    * msql(gid, sid, did, lid)
+      - This function is used to return modified SQL for the selected language node
+
+    * get_sql(data, lid)
+      - This function will generate sql from model data
+
+    * get_functions(gid, sid, did)
+      - This function returns the handler and inline functions for the selected language node
+
+    * sql(gid, sid, did, lid):
+      - This function will generate sql to show it in sql pane for the selected language node.
+    """
+
+    node_type = blueprint.node_type
+
+    parent_ids = [
+            {'type': 'int', 'id': 'gid'},
+            {'type': 'int', 'id': 'sid'},
+            {'type': 'int', 'id': 'did'}
+            ]
+    ids = [
+            {'type': 'int', 'id': 'lid'}
+            ]
+
+    operations = dict({
+        'obj': [
+            {'get': 'properties', 'put': 'update'},
+            {'get': 'list'}
+        ],
+        'nodes': [{'get': 'node'}, {'get': 'nodes'}],
+        'sql': [{'get': 'sql'}],
+        'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'stats': [{'get': 'statistics'}],
+        'dependency': [{'get': 'dependencies'}],
+        'dependent': [{'get': 'dependents'}],
+        'module.js': [{}, {}, {'get': 'module_js'}],
+        'get_functions': [{}, {'get': 'get_functions'}]
+    })
+
+    def _init_(self, **kwargs):
+        """
+        Method is used to initialize the LanguageView and it's base view.
+        Also initialize all the variables create/used dynamically like conn, template_path.
+
+        Args:
+            **kwargs:
+        """
+        self.conn = None
+        self.template_path = None
+
+        super(LanguageView, self).__init__(**kwargs)
+
+    def module_js(self):
+        """
+        This property defines (if javascript) exists for this node.
+        Override this property for your own logic.
+        """
+        return make_response(
+                render_template(
+                    "languages/js/languages.js",
+                    _=gettext
+                    ),
+                200, {'Content-Type': 'application/x-javascript'}
+                )
+
+    def check_precondition(f):
+        """
+        This function will behave as a decorator which will checks
+        database connection before running view, it will also attaches
+        manager,conn & template_path properties to self
+        """
+        @wraps(f)
+        def wrap(*args, **kwargs):
+            # Here args[0] will hold self & kwargs will hold gid,sid,did
+            self = args[0]
+            self.driver = get_driver(PG_DEFAULT_DRIVER)
+            self.manager = self.driver.connection_manager(kwargs['sid'])
+            self.conn = self.manager.connection(did=kwargs['did'])
+
+            # If DB not connected then return error to browser
+            if not self.conn.connected():
+                return precondition_required(
+                    gettext(
+                            "Connection to the server has been lost!"
+                    )
+                )
+
+            ver = self.manager.version
+            # we will set template path for sql scripts
+            if ver >= 90300:
+                self.template_path = 'languages/sql/9.3_plus'
+            else:
+                self.template_path = 'languages/sql/9.1_plus'
+
+            return f(*args, **kwargs)
+        return wrap
+
+    @check_precondition
+    def list(self, gid, sid, did):
+        """
+        This function is used to list all the language nodes within that collection.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+        """
+        sql = render_template("/".join([self.template_path, 'properties.sql']))
+        status, res = self.conn.execute_dict(sql)
+
+        if not status:
+            return internal_server_error(errormsg=res)
+        return ajax_response(
+                response=res['rows'],
+                status=200
+                )
+
+    @check_precondition
+    def nodes(self, gid, sid, did):
+        """
+        This function will used to create all the child node within that collection.
+        Here it will create all the language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+        """
+        res = []
+        sql = render_template("/".join([self.template_path, 'properties.sql']))
+        status, result = self.conn.execute_2darray(sql)
+        if not status:
+            return internal_server_error(errormsg=result)
+
+        for row in result['rows']:
+            res.append(
+                    self.blueprint.generate_browser_node(
+                        row['oid'],
+                        did,
+                        row['name'],
+                        icon="icon-language"
+                    ))
+
+        return make_json_response(
+                data=res,
+                status=200
+                )
+
+    @check_precondition
+    def properties(self, gid, sid, did, lid):
+        """
+        This function will show the properties of the selected language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            lid: Language ID
+        """
+        sql = render_template("/".join([self.template_path, 'properties.sql']), lid=lid)
+        status, res = self.conn.execute_dict(sql)
+
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        sql = render_template("/".join([self.template_path, 'acl.sql']), lid=lid)
+        status, result = self.conn.execute_dict(sql)
+        if not status:
+            return internal_server_error(errormsg=result)
+
+        # if no acl found then by default add public
+        if res['rows'][0]['acl'] is None:
+            res['rows'][0]['lanacl'] = dict()
+            res['rows'][0]['lanacl']['grantee'] = 'public'
+            res['rows'][0]['lanacl']['grantor'] = res['rows'][0]['lanowner']
+            res['rows'][0]['lanacl']['privileges'] = [{'privilege_type': 'U', 'privilege': True, 'with_grant': False}]
+        else:
+            for row in result['rows']:
+                priv = parse_priv_from_db(row)
+                if row['deftype'] in res['rows'][0]:
+                    res['rows'][0][row['deftype']].append(priv)
+                else:
+                    res['rows'][0][row['deftype']] = [priv]
+
+        return ajax_response(
+                response=res['rows'][0],
+                status=200
+                )
+
+    @check_precondition
+    def update(self, gid, sid, did, lid):
+        """
+        This function will update the data for the selected language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            lid: Language ID
+        """
+        data = request.form if request.form else json.loads(request.data.decode())
+        sql = self.get_sql(data, lid)
+
+        try:
+            if sql and sql.strip('\n') and sql.strip(' '):
+                status, res = self.conn.execute_dict(sql)
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                return make_json_response(
+                    success=1,
+                    info="Language updated",
+                    data={
+                        'id': lid,
+                        'did': did,
+                        'sid': sid,
+                        'gid': gid
+                    }
+                )
+            else:
+                return make_json_response(
+                    success=1,
+                    info="Nothing to update",
+                    data={
+                        'id': lid,
+                        'did': did,
+                        'sid': sid,
+                        'gid': gid
+                    }
+                )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def msql(self, gid, sid, did, lid=None):
+        """
+        This function is used to return modified SQL for the selected language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            lid: Language ID
+        """
+        data = {}
+        for k, v in request.args.items():
+            try:
+                data[k] = json.loads(v)
+            except ValueError:
+                data[k] = v
+
+        sql = self.get_sql(data, lid)
+        if sql and sql.strip('\n') and sql.strip(' '):
+            return make_json_response(
+                    data=sql,
+                    status=200
+                    )
+        else:
+            return make_json_response(
+                    data='-- Modified SQL --',
+                    status=200
+                    )
+
+    def get_sql(self, data, lid=None):
+        """
+        This function will generate sql from model data.
+
+        Args:
+            data: Contains the data of the selected language node.
+            lid: Language ID
+        """
+        required_args = [
+            'name', 'lanowner', 'description'
+        ]
+        try:
+            sql = ''
+            if lid is not None:
+                sql = render_template("/".join([self.template_path, 'properties.sql']), lid=lid)
+                status, res = self.conn.execute_dict(sql)
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                for key in ['lanacl']:
+                    if key in data and data[key] is not None:
+                        if 'added' in data[key]:
+                            data[key]['added'] = parse_priv_to_db(data[key]['added'])
+                        if 'changed' in data[key]:
+                            data[key]['changed'] = parse_priv_to_db(data[key]['changed'])
+                        if 'deleted' in data[key]:
+                            data[key]['deleted'] = parse_priv_to_db(data[key]['deleted'])
+
+                old_data = res['rows'][0]
+                for arg in required_args:
+                    if arg not in data:
+                        data[arg] = old_data[arg]
+                sql = render_template("/".join([self.template_path, 'update.sql']), data=data,
+                                      o_data=old_data, conn=self.conn)
+            return sql
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def get_functions(self, gid, sid, did):
+        """
+        This function returns the handler and inline functions for the selected language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+        """
+        sql = render_template("/".join([self.template_path, 'functions.sql']))
+        status, result = self.conn.execute_dict(sql)
+        if not status:
+            return internal_server_error(errormsg=result)
+        return make_json_response(
+                data=result['rows'],
+                status=200
+                )
+
+    @check_precondition
+    def sql(self, gid, sid, did, lid):
+        """
+        This function will generate sql to show it in sql pane for the selected language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            lid: Language ID
+        """
+        sql = render_template("/".join([self.template_path, 'properties.sql']), lid=lid)
+        status, res = self.conn.execute_dict(sql)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        # Making copy of output for future use
+        old_data = dict(res['rows'][0])
+        sql = render_template("/".join([self.template_path, 'sqlpane.sql']), data=old_data, conn=self.conn)
+
+        return ajax_response(response=sql)
+
+    @check_precondition
+    def dependents(self, gid, sid, did, lid):
+        """
+        This function get the dependents and return ajax response
+        for the language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            lid: Language ID
+        """
+        dependents_result = get_dependents(self.conn, lid, 'language')
+        return ajax_response(
+                response=dependents_result,
+                status=200
+                )
+
+    @check_precondition
+    def dependencies(self, gid, sid, did, lid):
+        """
+        This function get the dependencies and return ajax response
+        for the language node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            lid: Language ID
+        """
+        dependencies_result = get_dependencies(self.conn, lid, 'language')
+        return ajax_response(
+                response=dependencies_result,
+                status=200
+                )
+
+LanguageView.register_node_view(blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/static/img/coll-language.png b/web/pgadmin/browser/server_groups/servers/databases/languages/static/img/coll-language.png
new file mode 100644
index 0000000000000000000000000000000000000000..e730cb2ec034b8ad0860a945fde442e8b698c83d
GIT binary patch
literal 477
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}SAb85E0BJ3YvzMPkvBGK-q<Yv
z_^jpINB&<v#eaEq^wxIeH}|}M{7nDyA@0RB=X(cruWyvSy;JqY#fBfhGT%Q7xwXyW
z%e(l`Z)3l_Pk4IX?&UT2TicXx?@+z5N&eb8>7T!{zq~y1>v!(&-}&zz1poO{baS)9
zvvc+zpGN-rn)CNh$+fj|S5}Gr`&;(xY}x<66?UsN(t)mFED7=pW^j0RBMr#mEbxdd
z2GSm2>~=ES4#?>8ba4!kxE$JlQ>@8=hxKsWg{al8YedCe4mSP&U)?4&{ap03GlzK@
z90c3~B@Rrt@Z7B9o8(p=r!%ca^+?p2?N4UEU0&!k)p~#6)qD9%>~<Ure3EgdFpER)
z;*}e7I)WBjBo`~L@?=>3b?Sv8x#U^17aMMww)MOF^{=(Rt2quWmu2Jr-}CJ$w~6ur
zX+A&R+4(bNJ_B8)TH+c}l9E`GYL#4+3Zxi}3=9o)4UKdS3`2|ztW1opOiZ;6OsxzI
u=DpKfg`y!hKP5A*5~9Jt608BJ+QiDh45H!G^w2dx4Gf;HelF{r5}E*I-p~I4

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/static/img/language.png b/web/pgadmin/browser/server_groups/servers/databases/languages/static/img/language.png
new file mode 100644
index 0000000000000000000000000000000000000000..f391a0836c11c4bc3eb9d25e37340adf3e25d003
GIT binary patch
literal 465
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}dw@@fE0BJ4H1XC}ldG$x-rk;b
zbBn^`(-v<Y_<VXF^X*6KhesRkAJ%{WH0a0Aw7dJXKfR9n@iXJ;>B3jHJ%0Ymyt&2b
z>xaajzp}r6O#1aZ_swnZ-@o(j?brSKHsR0jg12|(Jv?Ik>3Q^@KSejUDm^`G_u*04
zkB=FDei#4!Q*vdM*uTG}&(4<p`&<71Z^e=6KGr~|FqQ=Q1v5B2yO9Rua29w(76WMy
zFm^kcZ3kpDdb&7<NL<c6_mZ#4K)~%H<IV4zPAv*`$UXSI-fsDoOA`wI)tYBoF*GH{
z`5b0CS{8Hud(3gZCwz+|x(?;4XD(a9nKwy1%8%jHs%xu+oQtnY@ho|}MQpx<{hcWb
z#rNNN`S_>%Q`v(SXV-scH!NM%y4?8OPq~)XwXYQue#$XVWA*#P5bMk*{PSFAAJ8$X
zC9V-ADTyViR>?)FK#IZ0z|cU~&`8(7FvQ5f%EZ{p#8lhB)XKnM-aEZjC>nC}Q!>*k
iAsP%U!5V<7O{@&eAR10h4_yP)z~JfX=d#Wzp$Py#z|P|U

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/js/languages.js b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/js/languages.js
new file mode 100644
index 0000000..d3caf50
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/js/languages.js
@@ -0,0 +1,192 @@
+define(
+  ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser',
+    'alertify', 'pgadmin.browser.collection', 'pgadmin.browser.server.privilege'],
+  function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+  // Extend the browser's node model class to create a security model
+  var SecurityModel = Backform.SecurityModel = pgAdmin.Browser.Node.Model.extend({
+    defaults: {
+      provider: null,
+      security_label: null
+    },
+
+    // Defining schema for the Security Label
+    schema: [{
+      id: 'provider', label: '{{ _('Provider') }}',
+      type: 'text', disabled: false
+    },{
+      id: 'security_label', label: '{{ _('Security Label') }}',
+      type: 'text', disabled: false
+    }],
+    /* validate function is used to validate the input given by
+     * the user. In case of error, message will be displayed on
+     * the GUI for the respective control.
+     */
+    validate: function() {
+      var errmsg = null;
+      if (_.isUndefined(this.get('security_label')) ||
+        _.isNull(this.get('security_label')) ||
+        String(this.get('security_label')).replace(/^\s+|\s+$/g, '') == '') {
+            errmsg =  '{{ _('Please specify the value for all the security providers.')}}';
+            this.errorModel.set('security_label', errmsg);
+            return errmsg;
+      } else {
+        this.errorModel.unset('security_label');
+      }
+      return null;
+    }
+  });
+
+  // Extend the browser's collection class for languages collection
+  if (!pgBrowser.Nodes['coll-language']) {
+    var languages = pgAdmin.Browser.Nodes['coll-language'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'language',
+        label: '{{ _('Languages') }}',
+        type: 'coll-language',
+        columns: ['name', 'lanowner', 'description']
+      });
+  };
+
+  // Extend the browser's node class for language node
+  if (!pgBrowser.Nodes['language']) {
+    pgAdmin.Browser.Nodes['language'] = pgAdmin.Browser.Node.extend({
+      parent_type: 'database',
+      type: 'language',
+      label: '{{ _('language') }}',
+      hasSQL:  true,
+      hasDepends: true,
+      Init: function() {
+
+        // Avoid multiple registration of menus
+        if (this.initialized)
+            return;
+
+        this.initialized = true;
+      },
+
+      // Defining model for language node
+      model: pgAdmin.Browser.Node.Model.extend({
+        defaults: {
+          name: undefined,
+          lanowner: undefined,
+          comment: undefined,
+          lanacl: [],
+          seclabels:[]
+        },
+
+        // Defining schema for the language node
+        schema: [{
+          id: 'name', label: '{{ _('Name') }}', cell: 'string',
+          type: 'text',
+        },{
+          id: 'oid', label:'{{ _('Oid') }}', cell: 'string',
+          type: 'text', disabled: true
+        },{
+          id: 'lanowner', label:'{{ _('Owner') }}', type: 'text',
+          control: Backform.NodeListByNameControl, node: 'role',
+          mode: ['edit', 'properties'], select2: { allowClear: false }
+        },{
+          id: 'description', label:'{{ _('Comment') }}', cell: 'string',
+          type: 'multiline'
+        },{
+          id: 'trusted', label:'{{ _('Trusted?') }}', type: 'switch', options: { onText: 'Yes', offText: 'No',
+          onColor: 'success', offColor: 'default', size: 'small'},
+          group: 'Definition', mode: ['edit', 'properties'],
+          disabled: function(m) {
+            return !(m.isNew());
+          }
+        },{
+          id: 'lanproc', label:'{{ _('Handler Function') }}', type: 'text', control: 'node-ajax-options',
+          group: 'Definition', mode: ['edit', 'properties'], url:'get_functions',
+          /* This function is used to populate the handler function
+           * for the selected language node. It will check if the property
+           * type is 'handler' then push the data into the result array.
+           */
+          transform: function(data) {
+            var res = [];
+            if (data && _.isArray(data)) {
+                _.each(data, function(d) {
+                  if (d.prop_type == 'handler') {
+                    res.push({label: d.label, value: d.label});
+                  }
+                })
+            }
+            return res;
+          }, disabled: function(m) {
+            return !(m.isNew());
+          }
+        },{
+          id: 'laninl', label:'{{ _('Inline Function') }}', type: 'text', control: 'node-ajax-options',
+          group: 'Definition', mode: ['edit', 'properties'], url:'get_functions',
+          /* This function is used to populate the inline function
+           * for the selected language node. It will check if the property
+           * type is 'inline' then push the data into the result array.
+           */
+          transform: function(data) {
+            var res = [];
+            if (data && _.isArray(data)) {
+                _.each(data, function(d) {
+                  if (d.prop_type == 'inline') {
+                    res.push({label: d.label, value: d.label});
+                  }
+                })
+            }
+            return res;
+          }, disabled: function(m) {
+            return !(m.isNew());
+          }
+        },{
+          id: 'lanval', label:'{{ _('Validator Function') }}', type: 'text', control: 'node-ajax-options',
+          group: 'Definition', mode: ['edit', 'properties'], url:'get_functions',
+          /* This function is used to populate the validator function
+           * for the selected language node. It will check if the property
+           * type is 'validator' then push the data into the result array.
+           */
+          transform: function(data) {
+            var res = [];
+            if (data && _.isArray(data)) {
+                _.each(data, function(d) {
+                  if (d.prop_type == 'validator') {
+                    res.push({label: d.label, value: d.label});
+                  }
+                })
+            }
+            return res;
+          }, disabled: function(m) {
+            return !(m.isNew());
+          }
+        },{
+          id: 'lanacl', label: '{{ _('Privileges') }}', type: 'collection', group: '{{ _('Security') }}',
+          model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend({privileges: ['U']}), control: 'unique-col-collection',
+          mode: ['properties', 'edit'], canAdd: true, canDelete: true, uniqueCol : ['grantee']
+         },{
+          id: 'seclabels', label: '{{ _('Security Labels') }}',
+          model: SecurityModel, editable: false, type: 'collection',
+          group: '{{ _('Security') }}', mode: ['edit'],
+          min_version: 90200, canAdd: true,
+          canEdit: false, canDelete: true, control: 'unique-col-collection'
+        }
+        ],
+        /* validate function is used to validate the input given by
+         * the user. In case of error, message will be displayed on
+         * the GUI for the respective control.
+         */
+        validate: function() {
+          var name = this.get('name');
+
+          if (_.isUndefined(name) || _.isNull(name) ||
+            String(name).replace(/^\s+|\s+$/g, '') == '') {
+            var msg = '{{ _('Name can not be empty!') }}';
+            this.errorModel.set('name', msg);
+            return msg;
+          } else {
+            this.errorModel.unset('name');
+          }
+          return null;
+        }
+      })
+    })
+  }
+  return pgBrowser.Nodes['coll-language'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/acl.sql
new file mode 100644
index 0000000..a88e24f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/acl.sql
@@ -0,0 +1,23 @@
+SELECT 'lanacl' as deftype, COALESCE(gt.rolname, 'public') grantee, g.rolname grantor,
+	array_agg(privilege_type) as privileges, array_agg(is_grantable) as grantable
+FROM
+	(SELECT
+		d.grantee, d.grantor, d.is_grantable,
+		CASE d.privilege_type
+		WHEN 'USAGE' THEN 'U'
+		ELSE 'UNKNOWN'
+		END AS privilege_type
+	FROM
+		(SELECT lanacl FROM pg_language lan
+		    LEFT OUTER JOIN pg_shdescription descr ON (lan.oid=descr.objoid AND descr.classoid='pg_language'::regclass)
+		WHERE lan.oid = {{ lid|qtLiteral }}::OID
+		) acl,
+		(SELECT (d).grantee AS grantee, (d).grantor AS grantor, (d).is_grantable AS is_grantable,
+			(d).privilege_type AS privilege_type
+		FROM (SELECT aclexplode(lanacl) as d FROM pg_language lan1
+			WHERE lan1.oid = {{ lid|qtLiteral }}::OID ) a
+		) d
+	) d
+LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/functions.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/functions.sql
new file mode 100644
index 0000000..6545e84
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/functions.sql
@@ -0,0 +1,15 @@
+SELECT
+    CASE WHEN nspname != 'pg_catalog' THEN quote_ident(nspname) || '.' || quote_ident(proname)
+    ELSE quote_ident(proname)
+    END AS label,
+    CASE
+    WHEN prorettype = 2280 THEN 'handler'
+    WHEN proargtypes[0] = 2281 THEN 'inline'
+    ELSE 'validator'
+    END AS prop_type
+FROM
+    pg_proc p JOIN pg_namespace nsp ON nsp.oid=pronamespace
+WHERE
+    prorettype=2280 OR
+    (prorettype=2278 AND proargtypes[0]=26) OR
+    (prorettype=2278 AND proargtypes[0]=2281)
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/properties.sql
new file mode 100644
index 0000000..6f6879d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/properties.sql
@@ -0,0 +1,12 @@
+SELECT lan.oid as oid, lanname as name, lanpltrusted as trusted, lanacl as acl, hp.proname as lanproc,
+	vp.proname as lanval, description, pg_get_userbyid(lan.lanowner) as lanowner, ip.proname as laninl,
+	(SELECT array_agg(label) FROM pg_seclabels sl1 WHERE sl1.objoid=lan.oid) AS labels,
+	(SELECT array_agg(provider) FROM pg_seclabels sl2 WHERE sl2.objoid=lan.oid) AS providers
+FROM pg_language lan JOIN pg_proc hp on hp.oid=lanplcallfoid LEFT OUTER JOIN pg_proc ip on ip.oid=laninline
+LEFT OUTER JOIN pg_proc vp on vp.oid=lanvalidator
+LEFT OUTER JOIN pg_description des ON (des.objoid=lan.oid AND des.objsubid=0 AND des.classoid='pg_language'::regclass)
+WHERE lanispl IS TRUE
+{% if lid %}
+AND lan.oid={{lid}}::int
+{% endif %}
+ORDER BY lanname
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/sqlpane.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/sqlpane.sql
new file mode 100644
index 0000000..de942f5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/sqlpane.sql
@@ -0,0 +1,19 @@
+-- Language: {{data.name}}
+
+-- DROP LANGUAGE {{ conn|qtIdent(data.name) }}
+{# ============= CREATE LANGUAGE Query ============= #}
+CREATE {% if data.trusted %}TRUSTED{% endif %} PROCEDURAL LANGUAGE {{ conn|qtIdent(data.name) }}
+{% if data.lanproc %}
+  HANDLER {{ conn|qtIdent(data.lanproc) }}
+{% endif %}
+{% if data.laninl %}
+  INLINE {{ conn|qtIdent(data.laninl) }}
+{% endif %}
+{% if data.lanval %}
+  VALIDATOR {{ conn|qtIdent(data.lanval) }}
+{% endif %};
+{# ============= ALTER LANGUAGE Query ============= #}
+{% if data.lanowner %}
+ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ conn|qtIdent(data.lanowner) }};
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/update.sql
new file mode 100644
index 0000000..5206284
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.1_plus/update.sql
@@ -0,0 +1,38 @@
+{% import 'macros/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{# ============= Update language name ============= #}
+{% if data.name != o_data.name %}
+ALTER LANGUAGE {{ conn|qtIdent(o_data.name) }}
+  RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{# ============= Update language user ============= #}
+{% if data.lanowner and data.lanowner != o_data.lanowner %}
+ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ conn|qtIdent(data.lanowner) }};
+{% endif %}
+{# ============= Update language comments ============= #}
+{% if data.description and data.description != o_data.description %}
+COMMENT ON LANGUAGE {{ conn|qtIdent(data.name) }}
+  IS '{{ data.description }}';
+{% endif %}
+{% endif %}
+
+{# Change the privileges #}
+{% if data.lanacl %}
+{% if 'deleted' in data.lanacl %}
+{% for priv in data.lanacl.deleted %}
+{{ PRIVILEGE.RESETALL(conn, 'LANGUAGE', priv.grantee, data.name) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.lanacl %}
+{% for priv in data.lanacl.changed %}
+{{ PRIVILEGE.RESETALL(conn, 'LANGUAGE', priv.grantee, data.name) }}
+{{ PRIVILEGE.APPLY(conn, 'LANGUAGE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.lanacl %}
+{% for priv in data.lanacl.added %}
+{{ PRIVILEGE.APPLY(conn, 'LANGUAGE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/acl.sql
new file mode 100644
index 0000000..3d75620
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/acl.sql
@@ -0,0 +1,19 @@
+SELECT 'lanacl' as deftype, COALESCE(gt.rolname, 'public') grantee, g.rolname grantor,
+	array_agg(privilege_type) as privileges, array_agg(is_grantable) as grantable
+FROM
+	(SELECT
+		d.grantee, d.grantor, d.is_grantable,
+		CASE d.privilege_type
+		WHEN 'USAGE' THEN 'U'
+		ELSE 'UNKNOWN'
+		END AS privilege_type
+	FROM
+		(SELECT lanacl FROM pg_language lan
+		    LEFT OUTER JOIN pg_shdescription descr ON (lan.oid=descr.objoid AND descr.classoid='pg_language'::regclass)
+		WHERE lan.oid = {{ lid|qtLiteral }}::OID
+		) acl,
+		aclexplode(lanacl) d
+	) d
+LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/functions.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/functions.sql
new file mode 100644
index 0000000..6545e84
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/functions.sql
@@ -0,0 +1,15 @@
+SELECT
+    CASE WHEN nspname != 'pg_catalog' THEN quote_ident(nspname) || '.' || quote_ident(proname)
+    ELSE quote_ident(proname)
+    END AS label,
+    CASE
+    WHEN prorettype = 2280 THEN 'handler'
+    WHEN proargtypes[0] = 2281 THEN 'inline'
+    ELSE 'validator'
+    END AS prop_type
+FROM
+    pg_proc p JOIN pg_namespace nsp ON nsp.oid=pronamespace
+WHERE
+    prorettype=2280 OR
+    (prorettype=2278 AND proargtypes[0]=26) OR
+    (prorettype=2278 AND proargtypes[0]=2281)
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/properties.sql
new file mode 100644
index 0000000..6f6879d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/properties.sql
@@ -0,0 +1,12 @@
+SELECT lan.oid as oid, lanname as name, lanpltrusted as trusted, lanacl as acl, hp.proname as lanproc,
+	vp.proname as lanval, description, pg_get_userbyid(lan.lanowner) as lanowner, ip.proname as laninl,
+	(SELECT array_agg(label) FROM pg_seclabels sl1 WHERE sl1.objoid=lan.oid) AS labels,
+	(SELECT array_agg(provider) FROM pg_seclabels sl2 WHERE sl2.objoid=lan.oid) AS providers
+FROM pg_language lan JOIN pg_proc hp on hp.oid=lanplcallfoid LEFT OUTER JOIN pg_proc ip on ip.oid=laninline
+LEFT OUTER JOIN pg_proc vp on vp.oid=lanvalidator
+LEFT OUTER JOIN pg_description des ON (des.objoid=lan.oid AND des.objsubid=0 AND des.classoid='pg_language'::regclass)
+WHERE lanispl IS TRUE
+{% if lid %}
+AND lan.oid={{lid}}::int
+{% endif %}
+ORDER BY lanname
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/sqlpane.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/sqlpane.sql
new file mode 100644
index 0000000..de942f5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/sqlpane.sql
@@ -0,0 +1,19 @@
+-- Language: {{data.name}}
+
+-- DROP LANGUAGE {{ conn|qtIdent(data.name) }}
+{# ============= CREATE LANGUAGE Query ============= #}
+CREATE {% if data.trusted %}TRUSTED{% endif %} PROCEDURAL LANGUAGE {{ conn|qtIdent(data.name) }}
+{% if data.lanproc %}
+  HANDLER {{ conn|qtIdent(data.lanproc) }}
+{% endif %}
+{% if data.laninl %}
+  INLINE {{ conn|qtIdent(data.laninl) }}
+{% endif %}
+{% if data.lanval %}
+  VALIDATOR {{ conn|qtIdent(data.lanval) }}
+{% endif %};
+{# ============= ALTER LANGUAGE Query ============= #}
+{% if data.lanowner %}
+ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ conn|qtIdent(data.lanowner) }};
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/update.sql
new file mode 100644
index 0000000..5206284
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/9.3_plus/update.sql
@@ -0,0 +1,38 @@
+{% import 'macros/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{# ============= Update language name ============= #}
+{% if data.name != o_data.name %}
+ALTER LANGUAGE {{ conn|qtIdent(o_data.name) }}
+  RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{# ============= Update language user ============= #}
+{% if data.lanowner and data.lanowner != o_data.lanowner %}
+ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ conn|qtIdent(data.lanowner) }};
+{% endif %}
+{# ============= Update language comments ============= #}
+{% if data.description and data.description != o_data.description %}
+COMMENT ON LANGUAGE {{ conn|qtIdent(data.name) }}
+  IS '{{ data.description }}';
+{% endif %}
+{% endif %}
+
+{# Change the privileges #}
+{% if data.lanacl %}
+{% if 'deleted' in data.lanacl %}
+{% for priv in data.lanacl.deleted %}
+{{ PRIVILEGE.RESETALL(conn, 'LANGUAGE', priv.grantee, data.name) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.lanacl %}
+{% for priv in data.lanacl.changed %}
+{{ PRIVILEGE.RESETALL(conn, 'LANGUAGE', priv.grantee, data.name) }}
+{{ PRIVILEGE.APPLY(conn, 'LANGUAGE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.lanacl %}
+{% for priv in data.lanacl.added %}
+{{ PRIVILEGE.APPLY(conn, 'LANGUAGE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{% endif %}
\ No newline at end of file
